访问多维D3 nest()汇总键和值

时间:2015-09-02 09:26:58

标签: arrays d3.js

我在访问已嵌套在D3中的数据时遇到问题。我相信我已经正确地嵌套和汇总了数据,但随后我似乎无法访问我创建的新密钥/值对。

原始数据是每个测试的JSON blob,其完成日期,主题区域和分数。我想要实现的是每天为每个主题在图表上绘制一组单独的平均分数据点。我之前使用过巢来获得总体每日得分,并且已经使用下面的代码中引用的比例成功地绘制了这个,但是两级层次结构让我变得更好。当我记录新的'嵌套数据'对象看起来对我来说是正确的(即预期的值都在那里并按照我的预期分组)。

我已经为这几个不同的版本工作但没有成功。我想知道我是否想要做一些没有设计巢的东西,或者只是因为我的阵列符号是错误的(很可能!)。下面的代码显示了我使用的基本框架。我缺少的是一个选择适当主题的过滤器,以及从汇总中获取平均每日分数的正确方法。

    // Takes original data and nest by date and then subject and rolls up on count of work and mean score 

    var dataToNest = data;
          nestedData = d3.nest()
            .key(function(el) {return el.dateCompleted})
            .key(function(el) {return el.subject})
            .rollup(function(leaves) {
              return {"numberCompleted": leaves.length,
                      "averageScore": d3.mean(leaves, function(d) {return(d.score)})}
            })
            .entries(dataToNest);

   // Format date as JS object

            nestedData.forEach(function (el) {
               el.key = new Date(el.key);
             });

   // Sort by date    

             nestedData.sort(function (a,b) {
               return a.key - b.key;
             });

     // Code for scales etc not included  

      d3.select("svg")
        .selectAll("circle")
        .data(nestedData)
        .filter(/* Filter by subject */)
        .enter()
        .append("circle")
        .attr("class", "subject")
        .attr("r", 5)
        .attr("cy", function (d) {/* Get the average score for the selected subject */})
        .attr("cx", function(d) {return xScale(d.key)});

我尝试过的一些事情:

对于过滤器,我尝试使用d.values.key ===' Algebra'

的各种迭代来选择第二个键(主题键)的值。

对于平均分数,我尝试使用d.values.values.averageScore的迭代进行访问,以及迭代第二个数组的索引的函数。

我强烈怀疑,这是我对javascript中数组结构和引用的理解的问题。我已经阅读了所有相关帖子,但它们似乎主要是关于使用nest()而不是从其中访问值。

更新

通过以下方式踏上了门:

svg.selectAll('.circle-group')
.data(nestedSubjectData)
.enter().append('g')
.attr('class', 'circle-group')
.attr('transform', function(d, i) {
    return 'translate(' + xScale(d.key) + ',0)';
    })
.selectAll('circle')
.data(function(d) {return d.values;})
.enter().append('circle')
 .attr('class', function(d) {return d.key;})
 .attr('cx', 0)
 .attr('cy', function(d) { return d.values.averageScore; })
 .attr('r', 5);

这为第二级每个数组中的averageScore数据点添加了一个圆,并应用了一个可用于区分主题的类。

1 个答案:

答案 0 :(得分:0)

感谢Lars和一些关于SO的相关问题,我深究这一点。代码如下。尝试了几种不同的方法后,我将嵌套顺序更改为更符合逻辑的顺序。由于日期和分数用于设置x / y坐标,因此更容易将它们保持在一个级别并将主题设置为第一级。这样可以更容易地分割出每个系列的样式和其他系列级交互(比如在可视化中打开或关闭整个主题)。

我的图表现在显示每个主题中每个每日平均分数的一个点,它们之间有一条线。你可以删除其中一个,它仍然可以正常工作。

我还没有收录数据,但它是一个JSON文档。同样地,我还没有包括我的所有音阶或svg创作。

// Nest data by subject and day and get average overall

var subjectDataToNest = data;
nestedSubjectData = d3.nest()
  .key(function(el) {return el.subject}) // Nest by subject first
  .key(function(el) {return el.dateAppeared}) // Within each subject array create an array for each day
  .sortKeys(d3.ascending) // Sort the daily arrays by date (but this doesn't work reliably)
  .rollup(function(leaves) {
    return {
            "averageScore" : d3.mean(leaves, function(d) {return(d.score)}) // Return the average score 
          }
  })
  .entries(subjectDataToNest);

// Draw circles for each subject and each 

svg.selectAll('.subject-group')
.data(nestedSubjectData)
.enter().append('g')
// Create a group to contain each circle and (eventually) the path
.attr('class', 'subject-group')
.attr("id", function(d) {return d.key;})
// Change the selection
.selectAll('circle')
// Change the data to return index of nested array
.data(function(d) {return d.values;})
.enter().append('circle')
// Convert string date (which is the key in the nested array) to object and apply scale
.attr('cx', function(d) {return xScale(new Date(d.key));})
.attr('cy', function(d) { return yScale(d.values.averageScore); })
.attr('r', 5);

 //Draw line

 // 1. d3.svg.line() line generator takes values and retuns x/y c-oords for each datapoint 

 var subjectPath = d3.svg.line()
   .x(function(d) {
     return xScale(new Date(d.key));})
   .y(function(d) {
     return yScale(d.values.averageScore);
     })

// 2. Select the subject group and append a path to each
 svg.selectAll(".subject-group")
   .data(nestedSubjectData)
   .append('path')
   .attr('class', 'subject-line')
   .attr("d", subjectPath)
   // Pass the second level of the nested array to subjectPath to generate x/y co-ords for the 
   .attr("d",function(d) {return subjectPath(d.values);});

有用的阅读:

Nested Selections

jshanley's nested selection JS Bin - 与问题Accessing Nested Array in a D3 variable

相关

Phoebe Bright's canonical D3 nest examples