简体   繁体   English

我将如何更改 d3 圆包中的过滤器?

[英]How would I change the filter in d3 circle pack?

I'm definitely getting more and more comfortable with d3, starting to explore the transitions and what not and beginning to really see how the data is put together.我肯定对 d3 越来越熟悉,开始探索过渡和什么不是,并开始真正了解数据是如何组合在一起的。

I'm working off a specific example, a bubble chart, http://bl.ocks.org/mbostock/4063269 :我正在研究一个具体的例子,一个气泡图, http : //bl.ocks.org/mbostock/4063269

在此处输入图片说明

I'm trying to repurpose it to represent population growth over time.我试图重新利用它来代表随着时间的推移人口增长。 Here's my JSON这是我的 JSON

{
"name":"Population over Time",
"children":[
    {
    "name": "1790",
    "children": [
        {"locID":"1","name": "New York city, NY", "size": 33131},
        {"locID":"2","name": "Philadelphia city, PA", "size": 28522},
        {"locID":"3","name": "Boston town, MA", "size": 18320},
        {"locID":"4","name": "Charleston city, SC", "size": 16359},
        {"locID":"5","name": "Baltimore town, MD", "size": 13503},
        {"locID":"6","name": "Northern Liberties township, PA", "size": 9913},
        {"locID":"7","name": "Salem town, MA", "size": 7921},
        {"locID":"8","name": "Newport town, RI", "size": 6716},
        {"locID":"9","name": "Providence town, RI", "size": 6380},
        {"locID":"10","name": "Marblehead town, MA", "size": 5661},
        {"locID":"11","name": "Southwark district, PA", "size": 5661},
        {"locID":"12","name": "Gloucester town, MA", "size": 5317},
        {"locID":"13","name": "Newburyport town, MA", "size": 4837},
        {"locID":"14","name": "Portsmouth town, NH", "size": 4720},
        {"locID":"15","name": "Sherburne town (Nantucket), MA", "size": 4620},
        {"locID":"16","name": "Middleborough town, MA", "size": 4526},
        {"locID":"17","name": "New Haven city, CT", "size": 4487},
        {"locID":"18","name": "Richmond city, VA", "size": 3761},
        {"locID":"19","name": "Albany city, NY", "size": 3498},
        {"locID":"20","name": "Norfolk borough, VA", "size": 2959},
        {"locID":"21","name": "Petersburg town, VA", "size": 2828},
        {"locID":"22","name": "Alexandria town, VA", "size": 2748},
        {"locID":"23","name": "Hartford city, CT", "size": 2683},
        {"locID":"24","name": "Hudson city, NY", "size": 2584}
        ]
    },
    {
    "name": "1800",
    "children": [
        {"locID":"1","name": "New York city, NY", "size": 60515},
        {"locID":"2","name": "Philadelphia city, PA", "size": 41220},
        {"locID":"25","name": "Baltimore city, MD", "size": 26514},
        {"locID":"3","name": "Boston town, MA", "size": 24937},
        {"locID":"4","name": "Charleston city, SC", "size": 18824},
        {"locID":"6","name": "Northern Liberties township, PA", "size": 10718},
        {"locID":"11","name": "Southwark district, PA", "size": 9621},
        {"locID":"7","name": "Salem town, MA", "size": 9457},
        {"locID":"9","name": "Providence town, RI", "size": 7614},
        {"locID":"20","name": "Norfolk borough, VA", "size": 6926},
        {"locID":"8","name": "Newport town, RI", "size": 6739},
        {"locID":"13","name": "Newburyport town, MA", "size": 5946},
        {"locID":"18","name": "Richmond city, VA", "size": 5737},
        {"locID":"26","name": "Nantucket town, MA", "size": 5617},
        {"locID":"14","name": "Portsmouth town, NH", "size": 5339},
        {"locID":"12","name": "Gloucester town, MA", "size": 5313},
        {"locID":"27","name": "Schenectady city, NY", "size": 5289},
        {"locID":"19","name": "Albany city, NY", "size": 5289},
        {"locID":"10","name": "Marblehead town, MA", "size": 5211},
        {"locID":"28","name": "New London city, CT", "size": 5150},
        {"locID":"29","name": "Savannah city, GA", "size": 5146},
        {"locID":"30","name": "Alexandria town, DC", "size": 4971},
        {"locID":"16","name": "Middleborough town, MA", "size": 4458},
        {"locID":"31","name": "New Bedford town, MA", "size": 4361},
        {"locID":"32","name": "Lancaster borough, PA", "size": 4292},
        {"locID":"17","name": "New Haven city, CT", "size": 4049},
        {"locID":"33","name": "Portland town, ME", "size": 3704},
        {"locID":"24","name": "Hudson city, NY", "size": 3664},
        {"locID":"23","name": "Hartford city, CT", "size": 3523},
        {"locID":"21","name": "Petersburg town, VA", "size": 3521},
        {"locID":"34","name": "Washington city, DC", "size": 3210},
        {"locID":"35","name": "Georgetown town, DC", "size": 2993},
        {"locID":"36","name": "York borough, PA", "size": 2503}
        ]
    }
    ]
}

Without doing much of the cool stuff, I've been able to start with showing a specific set of data per year, adjusting the filter has let me load it showing only a specific year, but it looks like this is the incorrect way, because if I manually change the filter to the following year, then it shows only bubbles for 1800, but there is white space in the center as if it still tried to load the 1790 bubbles.没有做很多很酷的事情,我已经能够从每年显示一组特定的数据开始,调整过滤器让我加载它只显示特定的年份,但看起来这是不正确的方式,因为如果我手动将过滤器更改为下一年,那么它只显示 1800 的气泡,但中间有空白区域,好像它仍然试图加载 1790 气泡。

var node = svg.selectAll(".node")
      .data(bubble.nodes(classes(root))
      .filter(function(d) {
        if(d.depth == 1 && d.packageName == year){
            return d;
        }
        else{
            return null;
        }
      }))
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

I'm also having a hard time finding a way to change that filter with a JS command, so that people can toggle between years.我也很难找到一种使用 JS 命令更改过滤器的方法,以便人们可以在年份之间切换。 How can I understand this a bit better?我怎样才能更好地理解这一点?

The problem is that the positions of all of the bubbles are determined when you create the layout, not when you append everything.问题是所有气泡的位置都是在创建布局时确定的,而不是在添加所有内容时确定。 If you want to create bubbles for only the 1800 points, you need to filter your data before applying the layout.如果只想为 1800 个点创建气泡,则需要在应用布局之前过滤数据。 It's not trying to load the bubbles, but they were part of the data that you passed to bubble.nodes.它不是试图加载气泡,但它们是您传递给bubble.nodes 的数据的一部分。 (Specifically, you passed them in classes(root). (具体来说,您在类(根)中传递了它们。

You can do this by using the javascript .filter method inside the .classes() function from the bubble chart example.您可以通过使用气泡图示例中.classes()函数内的 javascript .filter方法来完成此操作。

Here's an example where I changed it to only display the classes in the layout package:这是一个示例,我将其更改为仅显示layout包中的类:

// Returns a flattened hierarchy containing all leaf nodes under the root.
function classes(root) {
  var classes = [];

  function recurse(name, node) {
    if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
    else classes.push({packageName: name, className: node.name, value: node.size});
  }

  recurse(null, root);
  classes = classes.filter(function(thisClass){return thisClass.packageName == 'layout'}) 
  return {children: classes};
}

Also note that the filter function doesn't return the elements that I want, it returns a boolean for each element that says if I want it or not.另请注意,过滤器函数不返回我想要的元素,它为每个元素返回一个布尔值,表示我是否想要它。 It also doesn't modify the array it is used on, so classes == classes.filter() is required.它也不会修改它所使用的数组,因此需要classes == classes.filter()

I built a working fiddle of the bubble chart example here.在这里构建了气泡图示例的工作小提琴

In the original bubble chart, the filter removes some circles that appear behind the other circles.在原始气泡图中,过滤器删除了出现在其他圆圈后面的一些圆圈。

EDIT (ANSWER TO YOUR QUESTION):编辑(回答您的问题):

Store all of your data in a single data object.将所有数据存储在单个data对象中。 You can use a modified version of the classes function that contains an internal filter for a certain year.您可以使用包含特定年份的内部过滤器的classes函数的修改版本。 (Similar to what I did for filtering to a specific packageName in my example). (类似于我在示例中过滤特定packageName所做的工作)。 To update, select all nodes and enter your new data in them with the following:要更新,请选择所有节点并使用以下命令在其中输入新数据:

d3.selectAll('.node').data(bubble.nodes(modifiedClasses(root,year))

Note that this WILL NOT automatically update all of your nodes, just the data, just change the underlying data structure.请注意,这不会自动更新您的所有节点,只会更新数据,只会更改底层数据结构。 You'll then use the standard d3 enter/exit/update pattern to change your visualization.然后,您将使用标准的 d3 进入/退出/更新模式来更改您的可视化。 The best example of this structure is this block.这种结构的最好例子就是这个块。 I'd further recommend using keyed data for this, to differentiate between locations.我进一步建议为此使用键控数据,以区分位置。 If you use如果你使用

.data(bubble.nodes(modifiedClasses(root,year)),function(d){return d.locID}) 

Each element will correspond to a certain place.每个元素将对应一个特定的地方。 If you do this, instead of removing all data points and then rebuilding, you can remove all locations that don't exist at the new date (with some .exit() behavior), add any new locations (with .enter() ), and update any locations that exist at both years.如果你这样做,而不是删除所有数据点然后重建,你可以删除在新日期不存在的所有位置(使用一些.exit()行为),添加任何新位置(使用.enter() ) ,并更新这两年存在的任何位置。 Check out the next two blocks in the general update series (the block I linked above) for a good example of how to do this.查看常规更新系列中的下两个块(我在上面链接的块),以获得如何执行此操作的一个很好的示例。 If you can figure it out, you'll have a good handle on the basic workings of data manipulation in d3.如果你能弄清楚,你就会很好地掌握 d3 中数据操作的基本工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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