与复选框平行坐标 [英] Parallel Coordinates with check box

查看:224
本文介绍了与复选框平行坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些数据,我想使用平行坐标可视化它们。



我的数据包含200行(个案)和100列(功能)。我只需要可视化数据的一部分(200x8),包括feature1,feature2,...,feature8。另外,我有4列数据(A,B,C和D),它们的值为0或1.例如,如果一个案例(行)的列A的值为1,则意味着数据的类型是类型A。



我已经有用于绘制平行坐标的代码:

 < div class =filter_options> 
< input class =filter_buttonid =a_buttontype =checkbox> A< / input>< br>
< input class =filter_buttonid =b_buttontype =checkbox> B< / input>< br>
< input class =filter_buttonid =c_buttontype =checkbox> C< / input>< br&
< input class =filter_buttonid =d_buttontype =checkbox> D< / input>< br>
< / div>

< body>

< script type =text / javascript>

var m = [30,10,10,10],
w = 1300-m [1] -m [3],
h = 500-m [0] m [2];

var x = d3.scale.ordinal()。rangePoints([0,w],1),
y = {},
dragging = {}

var line = d3.svg.line(),
axis = d3.svg.axis()。orient(left),
background,
前景;

var svg = d3.select(body)append(svg:svg)
.attr(width,w + m [1] + m [3] )
.attr(height,h + m [0] + m [2])
.append(svg:g)
.attr (+ m [3] +,+ m [0] +));

d3.csv(myData.csv)
.row(function(d){
return {
//需要可视化的功能
feature1:d.feature1,
feature2:d.feature2,
feature3:d.feature3,
feature4:d.feature4,
feature5:d.feature5,
feature6:d.feature6,
feature7:d.feature7,
feature8:d.feature8,
A:dA,
B:dB,
:dC,
D:dD
};
})
.get(function(e,data){
x.domain(
dimensions = d3.keys(data [0])
.filter(function(d){
return d!=source&&
(y [d] = d3.scale。 linear()
.domain(d3.extent(data,function(p){return + p [d];}))
.range([h,0]));
}
));

//为上下文添加灰色背景线。
background = svg.append(svg:g)
.attr(class,background)
.selectAll(path)
.data )
.enter()。append(svg:path)
.attr(d,path);

//为焦点添加蓝色前景线。
foreground = svg.append(svg:g)
.attr(class,foreground)
.selectAll(path)
.data )
.enter()。append(svg:path)
.attr(d,path);

//为每个维添加一个组元素。
var g = svg.selectAll(。dimension)
.data(dimensions)
.enter()。append(svg:g)
.attr class,dimension)
.attr(transform,function(d){returntranslate(+ x(d)+);})
.call(d3.behavior .drag()
.on(dragstart,function(d){
dragging [d] = this .__ origin__ = x(d);
background.attr hidden);
})
.on(drag,function(d){
dragging [d] = Math.min(w,Math.max __origin__ + = d3.event.dx));
foreground.attr(d,path);
dimensions.sort(function(a,b){return position(a) - position );});
x.domain(dimensions);
g.attr(transform,function(d){returntranslate(+ position(d)+);}
})
.on(dragend,function(d){
delete this .__ origin__;
delete dragging [d];
transition(d3.select (this))。attr(transform,translate(+ x(d)+));
过渡(前景)
.attr(d,path);
background
.attr(d,path)
.transition()
.delay(500)
.duration(0)
.attr (visibility,null);
}));

//添加轴和标题。
g.append(svg:g)
.attr(class,axis)
.each(function(d){d3.select(this).call axis.scale(y [d]));})
.append(svg:text)
.attr(text-anchor,middle)
.attr y,-9)
.text(String);

//为每个轴添加并存储画笔。
g.append(svg:g)
.attr(class,brush)
.each(function(d){d3.select(this).call y [d] .brush = d3.svg.brush()。y(y [d])。on(brush,brush));})
.selectAll(rect)
.attr(x,-8)
.attr(width,16);
});

function position(d){
var v = dragging [d];
return v == null? x(d):v;
}

函数转换(g){
return g.transition()。duration(500);
}

//返回给定数据点的路径。
function path(d){
return line(dimensions.map(function(p){return [position(p),y [p](d [p])];})
}

//处理画刷事件,切换前景线的显示。
function brush(){
var actives = dimensions.filter(function(p){return!y [p] .brush.empty();}),
extents = actives.map (function(p){return y [p] .brush.extent();});
foreground.style(display,function(d){
return actives.every(function(p,i){
return extents [i] [0] p]& d [p]< = extents [i] [1];
})?null:none;
}
}

< / script>
< / body>

现在,我想添加4复选框,用户可以选择他/她想要的类型见并行坐标。例如,如果用户检查A类型,那么A列中值为1的情况(行)应该可视化。



我应该怎么做? / p>

我非常感谢您提供的任何帮助:)






此(5x31)数据块类似于我的数据:

 路径,Ktype,label,CGX,CGY,C_1 ,C_2,C_3,C_4,total1,total2,totalI3,total4,feature1,feature2,feature3,feature4,feature5,feature6,feature7,feature8,feature9,feature10,feature11,feature12,A,B,C,D,feature13,feature14 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,, 
.\Mydata\Case1,k1,1,42,33,0,57.44534,0,52597,71,16,10,276,4038,3789.631,0.6173469,0.6499337,2.103316,0.6661285 ,1.065539,248.3694,0.630161,0.000192848,0.9999996,0.000642777,1,0,0,1,9.60E-05,3136.698 ,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case2,k1,2,163,29, 0,43.28862,0,49050,71,16,10,248,2944,2587.956,0.5726808,0.5681185,2.130387,0.601512,1.137578,356.0444,0.6335613,0.000327267,1.000029,0.001271235,1,0,0,1,0.00010854,2676.418, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,
.\Mydata\Case3,k1,3,774,19,0,45.26291,0,53455,71,16,10,212,2366,1982.547,0.408179,0.4579566,1.994296,0.6615351,1.193415, 383.4534,0.7153812,0.000264522,1.000031,0.001210507,1,1,0,0,9.54E-05,3221.289 ,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case4,k1,4,1116,25,0 ,80.76469,0,57542,71,16,10,284,3908,3453.988,0.3549117,0.4811547,1.982244,0.6088744,1.131446,454.0122,0.6166388,0.000314288,0.9999836,0.00129846,0,1,1,0,0.000140592,2143.42 ,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,
.\Mydata\Case5,k1,5,1364,59,1,52.96776,0,49670,71,16,10,228,2725,2642.675,0.4328255,0.475517,1.859871,0.6587288,1.031152 ,82.32471,0.5775694,0.000466264,0.9999803,0.001765345,0,1,1,0,0.00012014,2439.636 ,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,


解决方案

在不知道你的数据和代码组织的情况下,给你一个建议或解决方案是相当困难的,所以我将尝试使用别人的类似和好的例子。 最终,您的问题的解决方案可能完全不同,但我将此答案作为指南发布给您,我希望它可以帮助您。



查看此。



数据在csv文件中,并且前几行如下:

 name,group,protein(g)钙(g),钠(g),纤维(g),维生素C(g),钾(g),碳水化合物(g),水(g),卡路里,饱和的(g),monounsat(g),polyunsat(g) ,巧克力,不重组,乳制品和蛋制品,19.9,0.285,0.385,0.4,0.07690000000000001,0.947,66.2,65.8,1.4,7.4,357,0.56,0.314,0.278,27481 
饮料,速溶早餐粉,巧克力,无糖,不重组,乳制品和蛋制品,35.8,0.5,0.717,2,0.138,1.705,41,39,5.1,7.4,358,2.162,1.189,1.027,27482
饮料,奶昔混合物,干燥,不巧克力,乳制品和蛋制品,23.5,0.88,0.78,1.6,0.0012,2.2,52.9,51.3,2.6,12.8,329,2.059,0.332,0.06 ,27483
黄油油,无水,乳制品和蛋制品,0.28,0.004,0.002,,0,0.005 ,,, 99.48,0.24,876,61.924,28.732,3.694,27484
黄油,盐渍,乳制品和蛋制品,0.85,0.024,0.714,,0,0.024,0.06,0.06,81.11,15.87,717,51.368,21.021,3.043,27485
黄油, with salt,Dairy and Egg Products,0.85,0.024,0.827,,0,0.026,0.06,0.06,81.11,15.87,717,50.489,23.426,3.012,27486
黄油,无盐, 乳制品和蛋制品,0.85,0.024,0.011,,0,0.024,0.06,0.06,81.11,17.94,717,51.368,21.021,3.043,27487
奶酪火锅,乳制品和蛋制品 ,14.23,0.476,0.132,,0,0.105,3.77,13.47,61.61,229,8.721,3.563,0.484,27488
奶酪食品,冷包装,美国,乳制品和蛋制品,19.66 ,0.497,0.966,,0,0.363,8.32,,24.46,43.12,331,15.355,7.165,0.719,27489
奶酪食品,模仿,乳制品和蛋制品,22.4,0.552,1.239, ,0,0.336,8.8,8,2,1,3,63.8,137,0.81,0.38,0.048,27490

第二列是组,此字段用于项目分类。在该示例中,还存在用于每个组的颜色的定义:

  var colors = {
Baby Foods :[185,56,73],
Baked Products:[37,50,75],
Beef Products:[325,50,39],
:[10,28,67],
早餐谷物:[271,39,57],
谷物和面食:[56,58,73],
乳制品和蛋制品:[28,100,52],
民族食品:[41,75,61],
快餐:[60,86,61],
脂肪和油:[30,100,73],
鱼和贝类产品:[318,65,67],
水果和果汁:[274,30,76] ,
Lamb,Veal和Game Products:[20,49,49],
豆类和豆类制品:[334,80,84],
,and sidedishes:[185,80,45],
Nut and Seed Products:[10,30,42],
Pork Products:[339,60,49],
家禽产品:[359,69,49],
餐馆食品:[204,70,41],
香肠和午餐肉类:[1,100,79]
Snacks:[189,57,75],
Soups,Sauces and Gravies:[110,57,70],
Spices and Herbs:[ 55,79],
Sweets:[339,60,75],
蔬菜和蔬菜产品:[120,56,40]
};

在图中间创建列表Food Groups的函数是create_legend / p>

  function create_legend(colors,brush){
//创建图例
var legend_data = d3.select #legend)
.html()
.selectAll(。row)
.data(_.keys(colors).sort())
b $ b //按组过滤
var legend = legend_data
.enter()。append(div)
.attr(title,Hide group)
.on(click,function(d){
//切换食物组
if(_.contains(excluded_groups,d)){
d3.select (title,Hide group)
excluded_groups = _.difference(excluded_groups,[d]);
brush();
} else {
d3.select这个).attr(title,Show group)
excluded_groups.push(d);
brush();
}
}

legend
.append(span)
.style(background,function(d,i){return color(d,0.85)})
.attr(class,color-bar);

legend
.append(span)
.attr(class,tally)
.text(function(d,i){return 0});

legend
.append(span)
.text(function(d,i){return+ d});

return legend;
}



如你所见,列表被实现为一系列的div有工具提示显示组或隐藏组,具体取决于相关组是否在列表excluded_groups中。此外,onclick事件会删除相关组,或将其添加到列表excluded_groups。在重绘平行坐标的代码中,列表excluded_groups用于过滤。你在代码中做类似的。这是所有的。



这个例子使用underscore.js用于各种目的,如果你不想这样,你可能需要重写和调整一些代码部分。


I have some data that I want to visualize them using parallel coordinates.

My data consists of 200 rows (cases) and 100 columns (features). I just need to visualize some part of data (200x8), including feature1, feature2, ..., feature8. Also I have 4 columns of data (A, B, C and D) that their values are either 0 or 1. For example if the value of column A for one case(row) is 1, it means that case of data is type A.

I already have the code for plotting parallel coordinates :

    <div class="filter_options">
<input class="filter_button" id="a_button" type="checkbox">A</input><br>
<input class="filter_button" id="b_button" type="checkbox">B</input><br>
<input class="filter_button" id="c_button" type="checkbox">C</input><br>
<input class="filter_button" id="d_button" type="checkbox">D</input><br>
</div>

  <body>

    <script type="text/javascript">

    var m = [30, 10, 10, 10],
        w = 1300 - m[1] - m[3],
        h = 500 - m[0] - m[2];

    var x = d3.scale.ordinal().rangePoints([0, w], 1),
        y = {},
        dragging = {};

    var line = d3.svg.line(),
        axis = d3.svg.axis().orient("left"),
        background,
        foreground;

 var svg = d3.select("body").append("svg:svg")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
  .append("svg:g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

  d3.csv("myData.csv")
  .row(function(d) {
    return {
    // Features that are needed to be visualize
     feature1   :  d.feature1,
     feature2   :  d.feature2,
     feature3   :  d.feature3,
     feature4   :  d.feature4,
     feature5   :  d.feature5,
     feature6   :  d.feature6,
     feature7   :  d.feature7,
     feature8   :  d.feature8,
     A : d.A,
     B : d.B,
     C : d.C,
     D : d.D
    };
  })
  .get(function(e, data) {
    x.domain(
        dimensions = d3.keys(data[0])
                        .filter(function(d) {
                                    return d != "source" && 
                                            (y[d] = d3.scale.linear()
                                                        .domain(d3.extent(data, function(p) { return +p[d]; }))
                                                        .range([h, 0]));
  }
  ));

  // Add grey background lines for context.
  background = svg.append("svg:g")
      .attr("class", "background")
    .selectAll("path")
      .data(data)
    .enter().append("svg:path")
      .attr("d", path);

  // Add blue foreground lines for focus.
  foreground = svg.append("svg:g")
      .attr("class", "foreground")
    .selectAll("path")
      .data(data)
    .enter().append("svg:path")
      .attr("d", path);

  // Add a group element for each dimension.
  var g = svg.selectAll(".dimension")
      .data(dimensions)
    .enter().append("svg:g")
      .attr("class", "dimension")
      .attr("transform", function(d) { return "translate(" + x(d) + ")"; })
      .call(d3.behavior.drag()
        .on("dragstart", function(d) {
          dragging[d] = this.__origin__ = x(d);
          background.attr("visibility", "hidden");
        })
        .on("drag", function(d) {
          dragging[d] = Math.min(w, Math.max(0, this.__origin__ += d3.event.dx));
          foreground.attr("d", path);
          dimensions.sort(function(a, b) { return position(a) - position(b); });
          x.domain(dimensions);
          g.attr("transform", function(d) { return "translate(" + position(d) + ")"; })
        })
        .on("dragend", function(d) {
          delete this.__origin__;
          delete dragging[d];
          transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
          transition(foreground)
              .attr("d", path);
          background
              .attr("d", path)
              .transition()
              .delay(500)
              .duration(0)
              .attr("visibility", null);
        }));

  // Add an axis and title.
  g.append("svg:g")
      .attr("class", "axis")
      .each(function(d) { d3.select(this).call(axis.scale(y[d])); })
    .append("svg:text")
      .attr("text-anchor", "middle")
      .attr("y", -9)
      .text(String);

  // Add and store a brush for each axis.
  g.append("svg:g")
      .attr("class", "brush")
      .each(function(d) { d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brush", brush)); })
    .selectAll("rect")
      .attr("x", -8)
      .attr("width", 16);
});

function position(d) {
  var v = dragging[d];
  return v == null ? x(d) : v;
}

function transition(g) {
  return g.transition().duration(500);
}

// Returns the path for a given data point.
function path(d) {
  return line(dimensions.map(function(p) { return [position(p), y[p](d[p])]; }));
}

// Handles a brush event, toggling the display of foreground lines.
function brush() {
  var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }),
      extents = actives.map(function(p) { return y[p].brush.extent(); });
  foreground.style("display", function(d) {
    return actives.every(function(p, i) {
      return extents[i][0] <= d[p] && d[p] <= extents[i][1];
    }) ? null : "none";
  });
}

    </script>
  </body>

Now, I want to add 4 check box that the user can select which types he/she wants to see in parallel coordinates. For example, if the user checks A-type, that cases (rows) with value of 1 in their A column should be visualized.

How should I do that?

I would really appreciate any help you could provide :)


This (5x31) chunk of data is something similar to my data:

path,Ktype,label,CGX,CGY,C_1,C_2,C_3,C_4,total1,total2,totalI3,total4,feature1,feature2,feature3,feature4,feature5,feature6,feature7,feature8,feature9,feature10,feature11,feature12,A,B,C,D,feature13,feature14,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case1,k1,1,42,33,0,57.44534,0,52597,71,16,10,276,4038,3789.631,0.6173469,0.6499337,2.103316,0.6661285,1.065539,248.3694,0.630161,0.000192848,0.9999996,0.000642777,1,0,0,1,9.60E-05,3136.698,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case2,k1,2,163,29,0,43.28862,0,49050,71,16,10,248,2944,2587.956,0.5726808,0.5681185,2.130387,0.601512,1.137578,356.0444,0.6335613,0.000327267,1.000029,0.001271235,1,0,0,1,0.00010854,2676.418,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case3,k1,3,774,19,0,45.26291,0,53455,71,16,10,212,2366,1982.547,0.408179,0.4579566,1.994296,0.6615351,1.193415,383.4534,0.7153812,0.000264522,1.000031,0.001210507,1,1,0,0,9.54E-05,3221.289,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case4,k1,4,1116,25,0,80.76469,0,57542,71,16,10,284,3908,3453.988,0.3549117,0.4811547,1.982244,0.6088744,1.131446,454.0122,0.6166388,0.000314288,0.9999836,0.00129846,0,1,1,0,0.000140592,2143.42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
.\Mydata\Case5,k1,5,1364,59,1,52.96776,0,49670,71,16,10,228,2725,2642.675,0.4328255,0.475517,1.859871,0.6587288,1.031152,82.32471,0.5775694,0.000466264,0.9999803,0.001765345,0,1,1,0,0.00012014,2439.636,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

解决方案

It is fairly hard to give you an advice or solution without knowing your data and code organization, so I will try to use someone else's similar and good example. Eventually, the solution to your question may look entirely different, but I post this answer as a guideline to you, and I hope it may help you.

Take a look at this fine example of usage of parallel coordinates: (it has the feature of selecting and deselecting groups of items - the exact feature you need)

JavaScript code for this example is here.

Data is in a csv file, and the first few lines are as follows:

"name","group","protein (g)","calcium (g)","sodium (g)","fiber (g)","vitaminc (g)","potassium (g)","carbohydrate (g)","sugars (g)","fat (g)","water (g)","calories","saturated (g)","monounsat (g)","polyunsat (g)","id"
"Beverage, instant breakfast powder, chocolate, not reconstituted","Dairy and Egg Products",19.9,0.285,0.385,0.4,0.07690000000000001,0.947,66.2,65.8,1.4,7.4,357,0.56,0.314,0.278,27481
"Beverage, instant breakfast powder, chocolate, sugar-free, not reconstituted","Dairy and Egg Products",35.8,0.5,0.717,2,0.138,1.705,41,39,5.1,7.4,358,2.162,1.189,1.027,27482
"Beverage, milkshake mix, dry, not chocolate","Dairy and Egg Products",23.5,0.88,0.78,1.6,0.0012,2.2,52.9,51.3,2.6,12.8,329,2.059,0.332,0.06,27483
"Butter oil, anhydrous","Dairy and Egg Products",0.28,0.004,0.002,,0,0.005,,,99.48,0.24,876,61.924,28.732,3.694,27484
"Butter, salted","Dairy and Egg Products",0.85,0.024,0.714,,0,0.024,0.06,0.06,81.11,15.87,717,51.368,21.021,3.043,27485
"Butter, whipped, with salt","Dairy and Egg Products",0.85,0.024,0.827,,0,0.026,0.06,0.06,81.11,15.87,717,50.489,23.426,3.012,27486
"Butter, without salt","Dairy and Egg Products",0.85,0.024,0.011,,0,0.024,0.06,0.06,81.11,17.94,717,51.368,21.021,3.043,27487
"Cheese fondue","Dairy and Egg Products",14.23,0.476,0.132,,0,0.105,3.77,,13.47,61.61,229,8.721,3.563,0.484,27488
"Cheese food, cold pack, american","Dairy and Egg Products",19.66,0.497,0.966,,0,0.363,8.32,,24.46,43.12,331,15.355,7.165,0.719,27489
"Cheese food, imitation","Dairy and Egg Products",22.4,0.552,1.239,,0,0.336,8.8,8.21,1.3,63.8,137,0.81,0.38,0.048,27490

Second column is "group", and this field is used for item classification. In this example, there is also definition of color used for each group:

var colors = {
  "Baby Foods": [185,56,73],
  "Baked Products": [37,50,75],
  "Beef Products": [325,50,39],
  "Beverages": [10,28,67],
  "Breakfast Cereals": [271,39,57],
  "Cereal Grains and Pasta": [56,58,73],
  "Dairy and Egg Products": [28,100,52],
  "Ethnic Foods": [41,75,61],
  "Fast Foods": [60,86,61],
  "Fats and Oils": [30,100,73],
  "Finfish and Shellfish Products": [318,65,67],
  "Fruits and Fruit Juices": [274,30,76],
  "Lamb, Veal, and Game Products": [20,49,49],
  "Legumes and Legume Products": [334,80,84],
  "Meals, Entrees, and Sidedishes": [185,80,45],
  "Nut and Seed Products": [10,30,42],
  "Pork Products": [339,60,49],
  "Poultry Products": [359,69,49],
  "Restaurant Foods": [204,70,41],
  "Sausages and Luncheon Meats": [1,100,79],
  "Snacks": [189,57,75],
  "Soups, Sauces, and Gravies": [110,57,70],
  "Spices and Herbs": [214,55,79],
  "Sweets": [339,60,75],
  "Vegetables and Vegetable Products": [120,56,40]
};

The function that creates list "Food Groups" in the middle of the diagram is create_legend():

function create_legend(colors,brush) {
  // create legend
  var legend_data = d3.select("#legend")
    .html("")
    .selectAll(".row")
    .data( _.keys(colors).sort() )

  // filter by group
  var legend = legend_data
    .enter().append("div")
      .attr("title", "Hide group")
      .on("click", function(d) { 
        // toggle food group
        if (_.contains(excluded_groups, d)) {
          d3.select(this).attr("title", "Hide group")
          excluded_groups = _.difference(excluded_groups,[d]);
          brush();
        } else {
          d3.select(this).attr("title", "Show group")
          excluded_groups.push(d);
          brush();
        }
      });

  legend
    .append("span")
    .style("background", function(d,i) { return color(d,0.85)})
    .attr("class", "color-bar");

  legend
    .append("span")
    .attr("class", "tally")
    .text(function(d,i) { return 0});  

  legend
    .append("span")
    .text(function(d,i) { return " " + d});  

  return legend;
}

As you can see, the list is implemented as a series of divs, that have tooltips "Show group" or "Hide group" depending on whether the group in question is in the list "excluded_groups". Also, "onclick" event removes the group in question from or adds it to the list "excluded_groups". In the code that redraws parallel coordinates, list "excluded_groups" is used for filtering. You do the similar in your code. That is all.

This example uses underscore.js for various purposes, if you do not want this, you may need to rewrite and adjust some code portions.

这篇关于与复选框平行坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆