簡體   English   中英

Javascript求和數組,使用d3.nest()

[英]Javascript summing arrays, using d3.nest()

如果我的數據看起來像這樣:

harvest = [{type: "apple", color: "green", value: 1}, 
           {type: "apple", color: "red", value: 2}, 
           {type: "grape", color: "green", value: 3},
           {type: "grape", color: "red", value: 4 }]

我可以使用d3的nest.rollup()函數通過各種屬性來總結它:

sum_by = "color";

rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
  return d3.sum(d, function(g) {
    return g.value;
  });
}).entries(harvest);

給我這個:

rollup = [{key: "green", values: 4},
          {key: "red", values: 6}]

這正是我想要的。

但是,我的數據中的值由數組組成,長度相等:

harvest = [{type: "apple", color: "green", values: [1,2,3,4]}, 
           {type: "apple", color: "red", values: [5,6,7,8]}, 
           {type: "grape", color: "green", values: [9,10,11,12]},
           {type: "grape", color: "red", values: [13,14,15,16] }]

是否有可能以類似的方式組合這些? 舉個例子:

rollup = [{key: "green", values: [10,12,14,16]},
          {key: "red", values: [18,20,22,24]}]

我覺得這可能是使用d3匯總功能(但不一定要使用d3)。

解析度

感謝@meetamit和@Superboggly的努力,我有三個解決方案:

版本1(首選,因為它只使用reduce()一次而map()只使用一次):

function sumArrays(group) {
  return group.reduce(function(prev, cur, index, arr) {
    return {
      values: prev.values.map(function(d, i) {
        return d + cur.values[i];
      })
    };
  });
}

版本2:

function sumArrays(group) {
  return group.map(function(h) {
    return h.values;
  }).reduce(function(prev, cur, index, arr) {
    return prev.map(function(d, i) {
      return d + cur[i];
    });
  });
}

版本3(感興趣,因為數組長度可能不同):

function sumArrays(group) {
  return group.reduce(function(prev, cur, index, arr) {
    return prev.map(function(d, i) {
      return d + cur.values[i];
    });
  }, [0, 0, 0, 0]);
}

這樣稱呼:

function rollupArrays() {
  return d3.nest().key(function(d) {
    return d[sum_by];
  }).rollup(sumArrays).entries(harvest);
}

並轉換為CoffeeScript:

rollupArrays = ->
  d3.nest().key (d) ->
    d[sum_by]
  .rollup(sumArrays).entries(harvest)

sumArrays = (group) ->
  group.reduce (prev, cur, index, arr) ->
    values: prev.values.map (d,i) ->
      d + cur.values[i]

UPDATE

如果函數必須運行,即使有一個輸入行,此方法也不適用。 第二部分

一種解決方案使用[].reduce()[].map()

// eg: sumArrays([ [1,2,3,4], [5,6,7,8] ]);// <- outputs [6, 8, 10, 12]
function sumArrays(arrays) {
  return arrays.reduce(
    function(memo, nums, i) {
      if(i == 0)
        return nums.concat();
      else
        return memo.map(
          function(memoNum, i) {
            return memoNum + nums[i];
          }
        );
    },
    [ ]// Start with empty Array for memo
  );
}

reduce和map都不是舊JS中的原生,所以最好使用一個模塊(下划線,或者可能有d3相當於reduce ,但我還沒有看到它)。

編輯

在代碼中使用它:

sum_by = "color";

rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
  var arraysToSum = d.map(function(g) { return g.values; });
  return sumArrays(arraysToSum)
}).entries(harvest);

@meetamit我喜歡你使用reduce的想法。

如果你想使用d3解決這個問題,它還有一個內置的reduce,你可以將它與nest函數一起使用:

var rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
    var result = d.reduce(function(prev, cur, index, arr) {
        return prev.values.map(function(d,i) { return d + cur.values[i];});
    });

    return result;
}).entries(harvest);

如果你想要你可以在這里玩它。

該解決方案利用了d3.rollupsd3.transpose ,新功能d3.array

 var input = [ { type: "apple", color: "green", values: [1, 2, 3, 4] }, { type: "apple", color: "red", values: [5, 6, 7, 8] }, { type: "grape", color: "green", values: [9, 10, 11, 12] }, { type: "grape", color: "red", values: [13, 14, 15, 16] } ]; var rolled_up = d3.rollups( input, vs => d3.transpose(vs.map(d => d.values)).map(vs => d3.sum(vs)), d => d.color ); var output = rolled_up.map(([color, values]) => ({ key: color, values: values })); console.log(output); 
 <script src="https://d3js.org/d3-array.v2.min.js"></script> 

這個:

  • 使用d3.rollups按顏色分組並減少生成的分組值:
    • 第3個參數是對項目進行分組的維度。
    • 第二個參數( vs => d3.transpose(vs.map(d => d.values)).map(vs => d3.sum(vs)) )是縮減函數,用於轉換分組值。
  • d3.transpose函數使用d3.transpose來壓縮分組數組,然后對得到的合並數組的每個部分求和
  • 將匯總產生的元素映射到預期的輸出格式。

這是d3.rollups產生的中間結果:

 var input = [ { type: "apple", color: "green", values: [1, 2, 3, 4] }, { type: "apple", color: "red", values: [5, 6, 7, 8] }, { type: "grape", color: "green", values: [9, 10, 11, 12] }, { type: "grape", color: "red", values: [13, 14, 15, 16] } ]; var rolled_up = d3.rollups( input, vs => d3.transpose(vs.map(d => d.values)).map(vs => d3.sum(vs)), d => d.color ); console.log(rolled_up); 
 <script src="https://d3js.org/d3-array.v2.min.js"></script> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM