1

假设我有一个格式如下的数据集:

var smallTestData = [
{"YEAR": "2009", "MONTH": "1", "CUSTOMER": "Customer1", "REVENUE": "1938.49488391425"},
{"YEAR": "2009", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "75.9142774343491"},
{"YEAR": "2009", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "99.3456067931875"} ...];

现在,如果我想绘制一个 D3 或 C3 图表来显示每个客户每年和每月的累计收入,我想我最终会得到这样的结果:

   [{"yearMonth":"2009 1","revenueCustomer1":158989,"revenueCustomer2":68181},
    {"yearMonth":"2009 2","revenueCustomer1":171217,"revenueCustomer2":204975},
    {"yearMonth":"2009 3","revenueCustomer1":38477,"revenueCustomer2":46605} ...];

当然,这看起来不是很优雅,但这没什么。最糟糕的部分是基于多个维度(例如 YEAR、MONTH、CUSTOMER)的度量值(例如 REVENUE)的聚合,这对于 JSON 数据来说是一件很痛苦的事情。

我尝试编写自己的聚合函数来解决这个问题,但除了手动将值相加之外找不到任何令人满意的解决方案。谁能指导我正确的方向?你将如何聚合你的数据以适应我描述的那种图表?有没有现成的解决方案?

既然我们正在讨论这个话题,那么您将如何根据主键加入两个或多个数据集?

谢谢!

4

2 回答 2

6

这似乎是摆脱困境的最佳时机d3.nest()。查看https://github.com/mbostock/d3/wiki/Arrays#-nest了解更多信息。

对于您的数据和您要执行的操作,您可以执行以下操作:

var nestedData = d3.nest().key(function(d) { return d.YEAR + " " + d.MONTH; })
                          .key(function(d) { return d.CUSTOMER; })
                          .rollup(function(leaves) {
                              return d3.sum(leaves, function(d) {
                                  return +d.REVENUE;
                              });
                           })
                           .entries(smallTestData);

这将返回一个类似于以下内容的对象:

[ 
    { 
        key: "2009 1",
        values: [
            { 
              key: "Customer1"
              values: 1938.49488391425
            },
            { 
              key: "Customer2"
              values: 175.2598842275366
            }
      },
      { ... }
]

工作方式d3.nestkey函数定义您希望聚合的对象属性,并且该rollup函数用于汇总与key函数匹配的所有数据。每个key函数都会创建一个新的嵌套深度。如果您没有该rollup函数,则valuesfor each 键将只是数据中与函数中定义的值匹配的所有值的数组key

于 2015-03-19T22:20:18.510 回答
3

var smallTestData = [
  {"YEAR": "2009", "MONTH": "1", "CUSTOMER": "Customer1", "REVENUE": "1938.49488391425"},
  {"YEAR": "2009", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "75.9142774343491"},
  {"YEAR": "2009", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "99.3456067931875"},
  {"YEAR": "2009", "MONTH": "2", "CUSTOMER": "Customer1", "REVENUE": "1938.49488391425"},
  {"YEAR": "2009", "MONTH": "2", "CUSTOMER": "Customer2", "REVENUE": "75.9142774343491"},
  {"YEAR": "2009", "MONTH": "2", "CUSTOMER": "Customer2", "REVENUE": "99.3456067931875"},
  {"YEAR": "2008", "MONTH": "1", "CUSTOMER": "Customer1", "REVENUE": "1938.49488391425"},
  {"YEAR": "2008", "MONTH": "1", "CUSTOMER": "Customer1", "REVENUE": "75.9142774343491"},
  {"YEAR": "2008", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "99.3456067931875"},
  {"YEAR": "2008", "MONTH": "2", "CUSTOMER": "Customer1", "REVENUE": "1938.49488391425"},
  {"YEAR": "2008", "MONTH": "2", "CUSTOMER": "Customer1", "REVENUE": "75.9142774343491"},
  {"YEAR": "2008", "MONTH": "2", "CUSTOMER": "Customer2", "REVENUE": "99.3456067931875"},
  {"YEAR": "2007", "MONTH": "1", "CUSTOMER": "Customer1", "REVENUE": "1938.49488391425"},
  {"YEAR": "2007", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "75.9142774343491"},
  {"YEAR": "2007", "MONTH": "1", "CUSTOMER": "Customer2", "REVENUE": "99.3456067931875"}
];

var nested = d3.nest()
  .key(function(d) { return d.CUSTOMER; }) // nest first by customer
  .key(function(d) { return d.YEAR; }) // then-by year
  .key(function(d) { return d.MONTH; }) // then-by month
  .rollup(function(values) {
    return d3.sum(values, function(d) { return d.REVENUE; });
  })
  .map(smallTestData)

console.log(nested);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

运行此代码段,打开控制台窗口并查看记录的结果。如果不是.map(nested)您使用.entries(nested),您会得到相同的东西,但表示为一系列嵌套数组,这可能会使绑定到 d3 选择更方便(使用他们的.data()方法)。

改变.key()函数的顺序可以控制嵌套的顺序。

于 2015-03-19T22:31:46.827 回答