【问题标题】:d3.nest() sum for object array datad3.nest() 对象数组数据的总和
【发布时间】:2015-07-01 12:44:12
【问题描述】:

我有

格式的数据
data={
  "Month": "Jan",
  "typeA": [
     {
        "A": 24000,
        "B": 24000,
        "C": 24000
     }],
  "typeB": [
     {
        "A": 20000,
        "B": 14000,
        "C": 10000
     }],
  "typeC": [
     {
        "A": 34000,
        "B": 44000,
        "C": 54000
     }]
     },
      {
  "Month": "Feb",
  "typeA": [
     {
        "A": 84000,
        "B": 64000,
        "C": 14000
     }],
  "typeB": [
     {
        "A": 20000,
        "B": 34000,
        "C": 10000
     }],
  "typeC": [
     {
        "A": 30000,
        "B": 40000,
        "C": 50000
     }]
    }
    ]

我想计算各个月份的每种类型(即typeA,TypeB)的总和, 即我想要以下格式的数据,

Month: jan
typeA:72000
typeB:44000
typeC:13200

Month:feb
typeA:162000
typeB:64000
typeC:120000

我正在使用 d3.nest() 来实现这一点,

这是我的代码,

    var months= d3.nest()
    .key(function (d) { return (d.Month) })
    .key(function (d) { return (d.typeA) })
    .key(function (d) { return (d.typeB) })
    .key(function (d) { return (d.typeC) })
      .rollup(function (leaves) {
          return d3.sum(leaves, function (d) { return d3.sum(sum,d3.values(d.A,d.B,d.C,d.D)) });
      })
      .entries(data);

我无法在这里得到元素的总和。我的总和为零。有人可以建议我哪里做错了吗?

【问题讨论】:

  • 您的数据不太正确,我认为应该有一个像这样的左方括号:data= [ {?
  • 这是示例数据。实际数据来自这种格式的服务。

标签: javascript d3.js


【解决方案1】:

不幸的是,我的另一个答案是针对不同的问题,但我会留下它以防万一它有用。

@Gabriel 的答案非常酷,但使用的是 d3 函数,但它不是通用的,并且类别是硬编码的,这并不理想。

这是一种在(主要是)完全通用的纯 JS 中执行此操作的方法。唯一的假设是每个数组元素的第一个成员是被分组的标题,而其他成员是要被汇总的成员。无论如何,以及通用的,这种方式是很短的。

我还包含了@Gabriel 答案的一个版本,以表明它也很容易概括。

  var data = [{
        "Month": "Jan",
        "typeA": [
          {
            "A": 24000,
            "B": 24000,
            "C": 24000
          }],
        "typeB": [
          {
            "A": 20000,
            "B": 14000,
            "C": 10000
          }],
        "typeC": [
          {
            "A": 34000,
            "B": 44000,
            "C": 54000
          }]
      },
      {
        "Month": "Feb",
        "typeA": [
          {
            "A": 84000,
            "B": 64000,
            "C": 14000
          }],
        "typeB": [
          {
            "A": 20000,
            "B": 34000,
            "C": 10000
          }],
        "typeC": [
          {
            "A": 30000,
            "B": 40000,
            "C": 50000
          }]
      }],
//////////////////////////////////////////////////////////////////////////////////
//Method one: without rollup
// assume that the first member of each object in the array is a heading
//  e.g. Month
//////////////////////////////////////////////////////////////////////////////////
  headings = data.reduce(function(headings, d) {
      var h = d3.keys(d)[0];  //get the heading
      return (headings [d[h]] = d3.keys(d).filter(function(p, i){return i}) //filter out the heading
        .reduce(function(s, p){   //sum each of the other members
          //p is the category being summed
          return (s[p] = d3.sum(d3.values(d[p][0])), s);
        }, {}), headings);
    }, {});

  d3.select("#output").text(JSON.stringify(headings));
//////////////////////////////////////////////////////////////////////////////////
//Method two: @Gabriel solution generalised
//////////////////////////////////////////////////////////////////////////////////
  var months = d3.nest()
    .key(function(d) { return (d.Month) })
    .rollup(function (v) {
      return d3.keys(v[0]).filter(function(p, i){return i}) //filter out the heading
        .reduce(function(s, p){   //sum each of the other members
          //p is the category being summed
          return (s[p] = d3.sum(d3.values(v[0][p][0])), s);
        }, {});
    })
    .map(data);

  d3.select("#output2").text(JSON.stringify(months));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="output"></div></br>
<div id="output2"></div>

【讨论】:

    【解决方案2】:

    我对@9​​87654321@不太熟悉。但我认为您可以使用 JavaScript Array map 函数获得结果。试试这个代码。

    var data=[{
      "Month": "Jan",
      "typeA": [
         {
            "A": 24000,
            "B": 24000,
            "C": 24000
         }],
      "typeB": [
         {
            "A": 20000,
            "B": 14000,
            "C": 10000
         }],
      "typeC": [
         {
            "A": 34000,
            "B": 44000,
            "C": 54000
         }]
         },
          {
      "Month": "Feb",
      "typeA": [
         {
            "A": 84000,
            "B": 64000,
            "C": 14000
         }],
      "typeB": [
         {
            "A": 20000,
            "B": 34000,
            "C": 10000
         }],
      "typeC": [
         {
            "A": 30000,
            "B": 40000,
            "C": 50000
         }]
        }
      ];
    
    var results = data.map(function(d){ 
      return { 
        Month: d.Month ,
        typeA: d3.sum(d3.values(d.typeA[0])),
        typeB: d3.sum(d3.values(d.typeB[0])),
        typeC: d3.sum(d3.values(d.typeC[0])) 
      } 
    });
    
    alert(JSON.stringify(results));
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;

    【讨论】:

      【解决方案3】:

      你可以用这样的嵌套来做到这一点......

        data = [{
          "Month": "Jan",
          "typeA": [
            {
              "A": 24000,
              "B": 24000,
              "C": 24000
            }],
          "typeB": [
            {
              "A": 20000,
              "B": 14000,
              "C": 10000
            }],
          "typeC": [
            {
              "A": 34000,
              "B": 44000,
              "C": 54000
            }]
        },
        {
          "Month": "Feb",
          "typeA": [
            {
              "A": 84000,
              "B": 64000,
              "C": 14000
            }],
          "typeB": [
            {
              "A": 20000,
              "B": 34000,
              "C": 10000
            }],
          "typeC": [
            {
              "A": 30000,
              "B": 40000,
              "C": 50000
            }]
        }],
          months = d3.nest()
      
        var months = d3.nest()
          .key(function(d){return d.Month})
          .rollup(function(leaves){
            //leaves is an array so use d3.sum
            return d3.sum(leaves, function(d) {
              //d can be an object who's value can be an array
              //use d3.sum
              return d3.sum(d3.values(d), function(e){
                //
                return d3.sum(e, function(f) {
                  return d3.sum(d3.values(f))
                });
              })
            } )
          })
          .entries(data);
        d3.select("#output").text(JSON.stringify(months));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
      <div id="output"></div>

      【讨论】:

        【解决方案4】:

        您只需要像这样更改您的代码:

        1. data 末尾添加];

          data = [
              {
                  "Month": "Jan",
                  "typeA": [
                      {
                          "A": 24000,
                          "B": 24000,
                          "C": 24000
                      }
                  ],
                  "typeB": [
                      {
                          "A": 20000,
                          "B": 14000,
                          "C": 10000
                      }
                  ],
                  "typeC": [
                      {
                          "A": 34000,
                          "B": 44000,
                          "C": 54000
                      }
                  ]
              },
              {
                  "Month": "Feb",
                  "typeA": [
                      {
                          "A": 84000,
                          "B": 64000,
                          "C": 14000
                      }
                  ],
                  "typeB": [
                      {
                          "A": 20000,
                          "B": 34000,
                          "C": 10000
                      }
                  ],
                  "typeC": [
                      {
                          "A": 30000,
                          "B": 40000,
                          "C": 50000
                      }
                  ]
              }
          ];
          
        2. 将您的代码更改为:

          var months = d3.nest()
              .key(function(d) { return (d.Month) })
              .rollup(function (v) {
                return {
          
                      typeA: d3.sum(d3.values(v[0].typeA[0])),
                      typeB: d3.sum(d3.values(v[0].typeB[0])),
                      typeC: d3.sum(d3.values(v[0].typeC[0]))
          
              } })
              .map(data);
          
          console.log(JSON.stringify(months));
          

          编辑: 您也可以使用这种类型的d3.sum() 函数,但请记住返回的值是string '您在代码中遗漏的部分' 以查看实际结果需要解析数据。

              var months = d3.nest()
              .key(function(d) { return (d.Month) })
              .rollup(function(v) {
                  return {
                      typeA: d3.sum(v, function(d) {
                          var type = d3.values(d.typeA[0]);
                          var array = type.map(function (x) { return parseInt(x, 10) });
                          return d3.sum(array);
                      }),
                      typeB: d3.sum(v, function (d) {
                          var type = d3.values(d.typeB[0]);
                          var array = type.map(function (x) { return parseInt(x, 10) });
                          return d3.sum(array);
                      }),
                      typeC: d3.sum(v, function (d) {
                          var type = d3.values(d.typeC[0]);
                          var array = type.map(function (x) { return parseInt(x, 10) });
                          return d3.sum(array);
                      })
          
                  }
              })
              .entries(data);
          
          console.log(JSON.stringify(months));
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-19
          • 2021-03-11
          • 1970-01-01
          相关资源
          最近更新 更多