objetos matriz especifico eliminar elementos elemento ejemplos comparar buscar array agregar javascript d3.js crossfilter dc.js

javascript - especifico - ¿Hay alguna manera de decirle a crossfilter que trate los elementos de la matriz como registros separados en lugar de tratar la matriz completa como una sola clave?



eliminar un elemento especifico de un array javascript (5)

El ejemplo anterior es un gran enfoque. Sin embargo, puedes dar un paso más. En la solución anterior, solo se filtrará según la primera selección que realice. Cualquier selección subsiguiente se ignora.

Si desea que responda a todas las selecciones, debería crear un filterHandler de la siguiente manera:

barChart.filterHandler (function (dimension, filters) { dimension.filter(null); if (filters.length === 0) dimension.filter(null); else dimension.filterFunction(function (d) { for (var i=0; i < d.length; i++) { if (filters.indexOf(d[i]) >= 0) return true; } return false; }); return filters; } );

Muestra de trabajo aquí: http://jsfiddle.net/jeffsteinmetz/cwShL/

Tengo un conjunto de datos donde algunos de los valores de campo son matrices y me gustaría utilizar crossfilter y d3.js o dc.js para mostrar el histograma de cuántas veces cada uno de esos valores estaba presente en el conjunto de datos.

Aquí hay un ejemplo:

var data = [ {"key":"KEY-1","tags":["tag1", "tag2"]}, {"key":"KEY-2","tags":["tag2"]}, {"key":"KEY-3","tags":["tag3", "tag1"]}]; var cf = crossfilter(data); var tags = cf.dimension(function(d){ return d.tags;}); var tagsGroup = tags.group(); dc.rowChart("#chart") .renderLabel(true) .dimension(tags) .group(tagsGroup) .xAxis().ticks(3); dc.renderAll();

Y JSFiddle http://jsfiddle.net/uhXf5/2/

Cuando ejecuto ese código produce un gráfico como este:

Pero lo que quiero es algo como esto:

Para complicar aún más las cosas, sería increíble poder hacer clic en cualquiera de las filas y filtrar el conjunto de datos con la etiqueta en la que se hizo clic.

Alguien tiene alguna idea de cómo lograr eso?

Gracias, Kostya



La respuesta de Jeff funciona, pero no es necesario realizar un seguimiento de la variable "encontrado" o continuar el ciclo si se encontró un elemento. Si X está en [X, Y, Z], esto ya ha reducido la cantidad de iteraciones en 1/3.

else dimension.filterFunction(function (d) { for (var i=0; i < d.length; i++) { if (filters.indexOf(d[i]) >= 0) return true; } return false; });

Alternativamente, podría parchear el método dc.js filterFunction y eso manejaría todos los casos.


Me gustaría tratar de proporcionar un contexto para el enfoque enumerado por Jeff y Kostya.

Notarás que el grupo de tags usa groupAll a diferencia del método de grupo típico. Crossfilter nos dice que "el objeto devuelto es similar a una agrupación estándar, excepto que no tiene métodos superiores ni de orden. En su lugar, use el valor para recuperar el valor reducido para todos los registros coincidentes". Kostya llamó al método ".value ()" para recuperar el único objeto que representa a todo el grupo.

var tagsGroup = tags.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value();

Este objeto no funcionará bien con dc.js porque dc.js espera que el objeto de grupo tenga un método all. Kostya parchó ese objeto para tener un método "todo" como ese:

// hack to make dc.js charts work tagsGroup.all = function() { var newObject = []; for (var key in this) { if (this.hasOwnProperty(key) && key != "all") { newObject.push({ key: key, value: this[key] }); } } return newObject; }

Esto funcionará con un simple gráfico dc.js, pero no podrá usar todas las funciones de dc.js ya que no todas las funciones de grupo están presentes. Por ejemplo, no podrá usar el método de "límite" en su tabla porque el método de límite espera que el objeto de grupo tenga un método "superior". También puedes parchar el método superior así:

topicsGroup.top = function(count) { var newObject = this.all(); newObject.sort(function(a, b){return b.value - a.value}); return newObject.slice(0, count); };

Esto permitirá que su gráfico use el método de límite:

barChart .renderLabel(true) .height(200) .dimension(topicsDim) .group(topicsGroup) .cap(2) .ordering(function(d){return -d.value;}) .xAxis().ticks(3);

Un ejemplo actualizado está disponible en http://jsfiddle.net/djmartin_umich/m7V89/#base


Resuelto por mí mismo, aquí está el violín con el código de trabajo http://jsfiddle.net/uhXf5/6/

Este es el código en caso de que alguien encuentre un problema similar:

function reduceAdd(p, v) { v.tags.forEach (function(val, idx) { p[val] = (p[val] || 0) + 1; //increment counts }); return p; } function reduceRemove(p, v) { v.tags.forEach (function(val, idx) { p[val] = (p[val] || 0) - 1; //decrement counts }); return p; } function reduceInitial() { return {}; } var data = [ {"key":"KEY-1","tags":["tag1", "tag2"], "date":new Date("10/02/2012")}, {"key":"KEY-2","tags":["tag2"], "date": new Date("10/05/2012")}, {"key":"KEY-3","tags":["tag3", "tag1"], "date":new Date("10/08/2012")}]; var cf = crossfilter(data); var tags = cf.dimension(function(d){ return d.tags;}); var tagsGroup = tags.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value(); // hack to make dc.js charts work tagsGroup.all = function() { var newObject = []; for (var key in this) { if (this.hasOwnProperty(key) && key != "all") { newObject.push({ key: key, value: this[key] }); } } return newObject; } var dates = cf.dimension(function(d){ return d.date;}); var datesGroup = dates.group(); var chart = dc.rowChart("#chart"); chart .renderLabel(true) .dimension(tags) .group(tagsGroup) .filterHandler(function(dimension, filter){ dimension.filter(function(d) {return chart.filter() != null ? d.indexOf(chart.filter()) >= 0 : true;}); // perform filtering return filter; // return the actual filter value }) .xAxis().ticks(3); var chart2 = dc.barChart("#chart2"); chart2 .width(500) .transitionDuration(800) .margins({top: 10, right: 50, bottom: 30, left: 40}) .dimension(dates) .group(datesGroup) .elasticY(true) .elasticX(true) .round(d3.time.day.round) .x(d3.time.scale()) .xUnits(d3.time.days) .centerBar(true) .renderHorizontalGridLines(true) .brushOn(true); dc.renderAll();