d3.js:如何从更多来源加入数据

use*_*379 2 d3.js

gs.csv(data1):

id, name, x_value, y_value
1, fruits, 60, 60
2, vegetables, 70, 70
...
Run Code Online (Sandbox Code Playgroud)

circles.csv(data2):

id, name, value, cx_value, cy_value
1, fruits, apple, 10, 10
2, fruits, pear, 20, 20
3, fruits, strawberry, 30, 30
4, vegetables, carrot, 40, 40
5, vegetables, celery, 50, 50
...
Run Code Online (Sandbox Code Playgroud)

我有两个数据文件,如上所述.gs.csv(data1)仅包含有关g元素的数据,而circle.csv(data2)仅包含有关圆的数据,我需要一种正确的方法来连接它们并创建以下内容:



    <g class="groups" id="fruits" transform="translate(60,90)">
      <circle class="some" id="apple" cx="10" cy="10"/>
      <circle class="some" id="pear" cx="20" cy="20"/>
      <circle class="some" id="strawberry" cx="30" cy="30"/>
      ...
    </g>
    <g class="groups" id="vegetables" transform="translate(70,70)">
      <circle class="some" id="carrot" cx="40" cy="40">
      <circle class="some" id="celery" cx="50" cy="50">
      ...
    </g>
Run Code Online (Sandbox Code Playgroud)

我无法加入文件,因为它们更复杂.我认为代码应该类似于:



    d3.csv("gs.csv", function(data1) {
     d3.csv("circles.csv", function(data2) {
       var svg = ...
       var groups = svg.selectAll(".groups")
                  .data(data1)
                  .enter().append("g")
                  .attr("class", "groups")
                  .attr("id", function(d) { return d.name; })
                  .attr("transform", function(d){return "translate(" + d.x_value + "," + d.y_value + ")"});

        groups.selectAll(".some")
        .data(data2, function(d) { return d.id; })
        .enter().append("circle")
        .attr("class", "some")
        .attr("id", function(d) { return d.value; })
        .attr("cx", function(d) { return d.cx_value; })
        .attr("cy", function(d) { return d.cy_value; });
    })
  });

Run Code Online (Sandbox Code Playgroud)

我想到了两个解决方案,但总有一些问题:首先,我尝试在第二个.data()中过滤来自data2的行,但我不知道如何访问实际组的属性来过滤所有圈子,除了那些相同的名称值.其次,我尝试使用密钥d.name来删除data2并将其输入到组中,但它会覆盖原始的__ data_ .所以,我尝试将键和值添加到每个组的_ data__但没有成功.

cke*_*sch 6

最简单的方法是将数据组放在一个列表中,然后对它们进行操作,如下所示:

groupData = [data1, data2];

groups = svg.selectAll('g')
    .data(groupData)
    .append('g')
Run Code Online (Sandbox Code Playgroud)

现在,您有两个组,每个组都附加了数据,用于组中所需的内容.您可以根据群组中的数据创建附加圈子的功能,然后为每个群组调用它.

function makeCircles(d){
    d3.select(this).selectAll('circle')
        .data(d)
        .append('circle')
        .attr('rx',function(D){return D.circleRadius})

groups.each(makeCircles);
Run Code Online (Sandbox Code Playgroud)

这将为您提供每个组的相关圈子.请注意,在selectAll我们创建的内部makeCircles,D指的是与给定圆关联的数据.我们可以使用d,但最好避免组数据d和圆形数据之间的可变混淆D.这样我们也可以在定义圆的属性的任何函数中使用它们.

如果我们希望第一个数据包含第二个数据,我们可以使用相同的函数,但使用基于d的过滤器替换D本身.代码如下所示:

var root = d3.select('body').append('svg'),

    data1 = [{'name':'foo','value':10},{'name':'foo','value':3},{'name':'foo','value':8},{'name':'bar','value':10},{'name':'bar','value':1},{'name':'bar','value':15}],

    data2 = [{'name':'foo','color':'green','x':10},{'name':'bar','color':'blue','x':70}];

console.log('foo')

var groups = root.selectAll('g')
    .data(data2)
    .enter()
    .append('g')
    .attr('transform',function(d){return 'translate(' + d.x + ',10)'})
    .each(addCircles);

function addCircles(d){
    d3.select(this).selectAll('circle')
        .data(data1.filter(function(D){return D.name == d.name }))
        .enter()
        .append('circle')
        .attr('r',5)
        .attr('cx', 0)
        .attr('cy', function(D){return D.value * 30})
        .style('fill',d.color)
}
Run Code Online (Sandbox Code Playgroud)

我在这里做了一个小提琴.