简体   繁体   中英

How to crossfilter histogram and scatterplot matrix in d3 v4?

I am using this kind of scatterplot matrix and a histogram as two views, in d3 . Both of them get the data from the same csv file. This is how the histogram looks like ( x axis ): 直方图

To brush the histogram I use the code below, which is similar to this snippet :

    svg.append("g")
        .attr("class", "brush")
        .call(d3.brushX()
        .on("end", brushed));

    function brushed() {
        if (!d3.event.sourceEvent) return;
        if (!d3.event.selection) return; 
        var d0 = d3.event.selection.map(x.invert),
            d1 = [Math.floor(d0[0]*10)/10, Math.ceil(d0[1]*10)/10];

        if (d1[0] >= d1[1]) {
            d1[0] = Math.floor(d0[0]);
            d1[1] = d1[0]+0.1;
        }

        d3.select(this).transition().call(d3.event.target.move, d1.map(x));
    }

How can I link the two views, so that when I brush the histogram, the scatterplot matrix will show the brushed points as colored in red , and the other points as, lets say, grey ?

This can get you started :

3 html files:

  • 2 for the visuals (histogram.html and scatter.html)
  • 1 to hold them in iframes (both.html):

Dependency:

  • jQuery (add to all 3 files)

Create table with 2 cells in both.html:

在此处输入图片说明

Add iframes to each cell:

<iframe id='histo_frame' width='100%' height='600px' src='histo.html'></iframe>
<iframe id='scatter_frame' width='100%' height='600px' src='scatter.html'></iframe>

在此处输入图片说明

I am using this histogram , and this scatterplot .

Add the linky_dink function to call the function inside your scatter.html (see below...):

function linky_dink(linked_data) {
   document.getElementById('scatter_frame').contentWindow.color_by_value(linked_data);
}

In your scatter.html change your cell.selectAll function to this:

cell.selectAll("circle")
        .data(data)
        .enter().append("circle")
        .attr("cx", function(d) { return x(d[p.x]); })
        .attr("cy", function(d) { return y(d[p.y]); })
        .attr("r", 4)
        .attr('data-x', function(d) { return d.frequency }) // get x value being plotted
        .attr('data-y', function(d) { return d.year }) // get y value being plotted
        .attr("class", "all_circles") // add custom class 
        .style("fill", function(d) { return color(d.species); });
  }

Note the added lines in bold:

在此处输入图片说明

Now our histogram circle elements retain the x and y values , along with a custom class we can use for targeting.

Create a color_by_value function :

function color_by_value(passed_value) {
    $('.all_circles').each(function(d, val) { 
    if(Number($(this).attr('data-x')) == passed_value) {
    $(this).css({ fill: "#ff0000" })
    }
    });
}

We know from above this function will be called from the linky_dink function of the parent html file. If the passed value matches that of the circle it will be recolored to #ff0000.

Finally, look for the brushend() function inside your histogram.html file. Find where it says: d3.selectAll("rect.bar").style("opacity", function(d, i) { .... and change to:

d3.selectAll("rect.bar").style("opacity", function(d, i) {
      if(d.x >= localBrushYearStart && d.x <= localBrushYearEnd || brush.empty()) {
      parent.linky_dink(d.y)
      return(1)
      } else {
      return(.4)
      }
    });

Now, in addition to controlling the rect opacity on brushing, we are also calling our linky_dink function in our both.html file, thus passing any brushed histogram value onto the scatterplot matrix for recoloring.

Result :

在此处输入图片说明

Not the greatest solution for obvious reasons. It only recolors the scatterplot when the brushing ends. It targets circles by sweeping over all classes which is horribly inefficient. The colored circles are not uncolored when the brushing leaves those values since this overwhelms the linky_dink function. And I imagine you'd rather not use iframes, let alone 3 independent files. Finally, jQuery isn't really needed as D3 provides the needed functionality. But there was also no posted solution, so perhaps this will help you or someone else come up with a better answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM