Search code examples
javascriptd3.jsdata-visualizationparallel-coordinates

Not all coordinates are plotted using parallel-coordinates (d3)


I am trying to use the parallel-coordinates library to plot some data. The coordinates of the data points that I have are all strings. Consider for example the following CSV table:

ID,TYPE,USER,OS,FooBar,Country
a1,X,1S,iOS,foo,US
a2,Y,1S,Android,bar,US

These are two data points, each having six attributes. The html MWE that I have is the following:

<!doctype html>

<link rel="stylesheet" type="text/css" href="d3.parcoords.css">
<script src="./d3.min.js"></script>
<script src="./d3.parcoords.js"></script>
<script src="./divgrid.js"></script>


<style>
/* data table styles */
#grid { height: 198px; }
.row, .header { clear: left; font-size: 12px; line-height: 18px; height: 18px; }
.row:nth-child(odd) { background: rgba(0,0,0,0.05); }
.header { font-weight: bold; }
.cell { float: left; overflow: hidden; white-space: nowrap; width: 100px; height: 18px; }
.col-0 { width: 180px; }
.col-1 { width: 80px; }
.col-2 { width: 180px; }
.col-3 { width: 150px;}
</style>

<title>Minimal Working Example</title>

<body>
<div id="visual" class="parcoords" style="width:1280px;height:350px"></div>
<p>Lines from the data</p>
<div id="grid"></div>
</body>


<!-- Setting and inserting the visualization and the corresponding table -->
<script>
 var parcoords = d3.parcoords()("#visual").color("steelblue");

 /*
 Load the data and visualize it
  */
 d3.csv('first-100.csv',function(data) {
   parcoords.data(data)
        .tickFormat(function(d) {return'';})
        .render().brushable().reorderable();

   var grid = d3.divgrid();
   d3.select("#grid")
     .datum(data.slice(0,30))
     .call(grid)
     .selectAll(".row")
     .on({
     "mouseover": function(d) { parcoords.highlight([d]) },
     "mouseout": parcoords.unhighlight
     });

   // update data table on brush event
   parcoords.on("brush", function(d) {
     d3.select("#grid")
       .datum(d.slice(0,30))
       .call(grid)
       .selectAll(".row")
       .on({
       "mouseover": function(d) { parcoords.highlight([d]) },
       "mouseout": parcoords.unhighlight
     });
   });
 });
</script>

Unfortunately, as you can see in the screenshot, this plots only four (4) coordinates... I believe that the problem is somehow related to the fact that all the coordinates are strings, but I'm not sure.

enter image description here

Any suggestions how to correct this?


Solution

  • The problem is that the parallel coordinates library filters out dimensions that have fewer than two unique values in the dataset, which is the case for the 'USER' and 'Country' columns in your data.

    The relevant source code is HERE. Line 168 in the current version of d3.parcoords.js, and it originates in the autoscale.js file in the src directory. Here is the code in case the link breaks:

    // hack to remove ordinal dimensions with many values
    pc.dimensions(pc.dimensions().filter(function(p,i) {
      var uniques = yscale[p].domain().length;
      if (__.types[p] == "string" && (uniques > 60 || uniques < 2)) {
        return false;
      }
      return true;
    }));
    

    One solution in your case, if you want to force the rendering of the two columns in question, is to simply comment out this block in the d3.parcoords.js file.

    Here is a PLUNK of your example where I have commented out the above code block. Now the output is as you expect. Hope that helps.