I am brushing a histogram using d3.js
, and am using crossfilter.js
for filtering the views:
var chart = scatterPlot()
.width(350)
.height(350)
.x(function (d) { return d.key[0] })
.y(function (d) { return d.key[1] });
d3.csv("data.csv", function (data) {// data in form of x,y,z,x1,y1
var csData = crossfilter(data);
// scatterplot data
csData.dimScatter = csData.dimension(function (d) {
return [parseFloat(d.x1), parseFloat(d.y1)];
});
csData.byScatter = csData.dimScatter.group();
csData.dimHistogram = csData.dimension(function (d) {
return Math.floor(parseFloat(d.z) * 10) / 10;
});
csData.byHistogram = csData.dimHistogram.group();
histogram1.onBrushed(function (selected) {
csData.dimHistogram.filter(selected);
update();
});
function update() {
d3.select("#scatterplot")
.datum(csData.byScatter.all())
.call(chart);
d3.select("#histogram")
.datum(csData.byHistogram.all())
.call(histogram1);
}
update();
});
Even though the histogram gets brushed(selected
shows the data that I brush), the data does not get filtered. Why is that occurring ?
Edit 1 - added JSFiddle
Edit 2 - code for chart
:
function scatterPlot() {
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 350,
height = 350,
innerWidth = width - margin.left - margin.right,
innerHeight = height - margin.top - margin.bottom,
xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; },
xScale = d3.scaleLinear(),
yScale = d3.scaleLinear();
function chart(selection) {
selection.each(function (data) {
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create the skeletal chart.
var svgEnter = svg.enter().append("svg");
var gEnter = svgEnter.append("g");
gEnter.append("g").attr("class", "x axis");
gEnter.append("g").attr("class", "y axis");
// Update the outer dimensions.
svg.merge(svgEnter).attr("width", width)
.attr("height", height);
// Update the inner dimensions.
var g = svg.merge(svgEnter).select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
xScale.rangeRound([0, innerWidth])
//d3.max(data, function(d) { return d.x1; })
.domain([-1.5, 1.5]);
yScale.rangeRound([innerHeight, 0])
.domain([-1.5, 1.5]);
g.select(".x.axis")
.attr("transform", "translate(0," + innerHeight + ")")
.call(d3.axisBottom(xScale));
g.select(".y.axis")
.call(d3.axisLeft(yScale).ticks(10))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
var points = g.selectAll(".point")
.data(function (d) { return d; });
points.enter().append("circle")
.attr("class", "point")
.merge(points)
.attr("cx", X)
.attr("cy", Y)
.attr("r", 2.5);
points.exit().remove();
});
}
// The x-accessor for the path generator; xScale ∘ xValue.
function X(d) {
return xScale(xValue(d));
}
// The y-accessor for the path generator; yScale ∘ yValue.
function Y(d) {
return yScale(yValue(d));
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
return chart;
}
Edit 3: Running Fiddle
Here's an updated fiddle that is working: https://jsfiddle.net/yquuhs3z/15/
More or less, you want to take a look at the data returned by csData.byScatter.all()
. Notably, groups that have no records in them don't go away, they just end up with a value of 0
, so you need to filter out groups you don't want based on their value before charting them. The means replacing
d3.select("#scatterplot")
.datum(csData.byScatter.all())
with
d3.select("#scatterplot")
.datum(csData.byScatter.all().filter(d => d.value !== 0))
The example also includes some logging using console.log
that may help you work this kind of thing out in the future, though many people prefer using the Javascript debugger for this kind of thing.