如何使用 d3 过滤器和更新功能在数据选择之间切换

Posted

技术标签:

【中文标题】如何使用 d3 过滤器和更新功能在数据选择之间切换【英文标题】:How to use d3 filter and update function to toggle between data selections 【发布时间】:2015-11-08 16:27:38 【问题描述】:

我试图通过根据房产地址是否以“街道”、“道路”、“路”等结尾来创建房价条形图来掌握 d3。

但是,我还希望根据本地社区的一列数据更改数据视图。

这是关于这个主题的第二个查询。这是上一个查询 - How to extract nominal labels for d3 chart

您可以在此处查看通过 Pandas 的 to_json 函数提取的数据的结构:http://plnkr.co/edit/He3yPUfuE8k7hvIkupjS?p=preview

我使用了嵌套函数来键入本地区域的数据,但不知道如何插入 d3.filter 方法来将数据限制到选定区域。

我有一个基于按键创建选择按钮的函数:

var options = dropDown.selectAll("option")
           .data(nested_data)

         .enter()
           .append("option");


          options.text(function (d)  return d.key; )
                                    .attr("value", function (d)  return d.key; );

但我无法解决的是如何将此选择中的值插入 d3 脚本的绘图部分。

d3.select("svg")
            .selectAll("circle")
            .data(nested_data)
            .enter()
            .append("circle")


          d3.selectAll("circle")            
            .attr("cx", function(d) 
                console.log(d["street_name"]);
                return street_scale(d["street_name"]);
            )
            .attr("cy", function(d) 
                return price_scale(d["value"]);
            )
            .attr("r", 5)
            .attr("fill", "steelblue");

虽然我知道我需要一个更新功能来继续在用户选择时更改图表,但我还没有找到可以适应的示例。

提前感谢您的耐心等待 - 我对 d3 和 javascript 菜鸟非常陌生。

【问题讨论】:

条形到底代表什么值?该地区该街道类型的值的总和?均值?中位数? @Mark 所代表的价值是该地区过去一年出售的房产的平均值。我已经在 Pandas 中完成了聚合,但无法找到将这些数字变成有用的东西的方法。希望这是有道理的。 @Mark 如果我没有正确使用嵌套功能,请给我打电话。我仍在尝试掌握 d3 中的数据函数,只是认为密钥会有所帮助。 给我几分钟,找出答案。我认为嵌套功能过于复杂。您可以使用更简单的数据结构来实现您的目标。 【参考方案1】:

想想你最终想要的数据结构。由于d3 喜欢对象数组,并且您想按地区过滤,所以我在想象这个:

var data = 
  district1: [
    
      street_split: 'a',
      value: 1
    ,
      street_split: 'b',
      value: 2
    
 ],
 district2: [
    
      street_split: 'a',
      value: 1
    ,
      street_split: 'b',
      value: 2
    
 ],
 etc...

然后你的过滤器就变成了:

data[someDistrict]

那么,我们如何以这种格式获取您的数据。我会在一个循环中完成所有事情,数据、范围、标签等......:

  var orgData = , // our final data like above
      street_labels = d3.set(), // set of streets
      districts = d3.set(), // set of districts
      minVal = 1e99, // min of values
      maxVal = -1e99; //max of values
  data.forEach(function(d)
    d.value = +d.value; // convert to numeric
    street_labels.add(d.street_split); // set of street_labels
    districts.add(d.district); // set of districts
    if (d.value < minVal) minVal = d.value; // new min?
    if (d.value > maxVal) maxVal = d.value; //new max?
    if (!orgData[d.district]) // we want a associate array with keys of districts
      orgData[d.district] = []; // and values that are arrays of object
    
    orgData[d.district].push( // those objects are street_split and value
      street_split: d.street_split,
      value: d.value
    );
  );

现在我们如何更新不同的选择?就变成了:

dropDown.on("change", function() 
    d3.selectAll("circle")
      .data(orgData[this.value]) // new data
      .attr("cx", function(d)  // update attributes
        return street_scale(d.street_split);
      )
      .attr("cy", function(d) 
        return price_scale(d.value);
      );
  );

这是我的working code。

【讨论】:

我非常感谢这个答案。它明确设定了一个目标,具有出色的 cmets 和清晰的逻辑。感谢您的宝贵时间。

以上是关于如何使用 d3 过滤器和更新功能在数据选择之间切换的主要内容,如果未能解决你的问题,请参考以下文章

D3 .merge 函数

D3.js 不更新数据

使用动态菜单时,闪亮的传单无法正常工作

sdl2 opengl d3d9的mipmap和各项异性过滤渲染

如何更新详细信息表中的数据并且不丢失范围选择和过滤器?

d3.js制作条形时间范围选择器