You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用D3将数据按月份分组,获取含日均金额的数组Map?

用D3实现按月份分组的每日平均金额转换

嘿,刚接触D3的话,确实会对这些分组聚合的函数有点摸不着头脑,我来帮你搞定这个需求!

你的思路其实是对的,用d3.rollup已经完成了核心的聚合计算,只是需要把得到的嵌套Map转换成你想要的对象+数组格式就行。咱们一步步来:

核心问题分析

你写的d3.rollup代码得到的是一个嵌套Map(Map<string, Map<string, number>>),比如:

Map(1) {"jan" => Map(3) {"mon" => 4, "tue" => 2, "wed" => 2}}

而你需要把这个结构转换成普通对象,同时把每个月份下的每日Map转成指定格式的数组。另外要注意:原始数据里的amount是字符串,直接用d3.mean会计算错误,得先转成数字!

完整实现代码

const data = [ 
  {day: "mon", amount: "4", month: "jan"}, 
  {day: "tue", amount: "2", month: "jan"}, 
  {day: "wed", amount: "3", month: "jan"}, 
  {day: "wed", amount: "1", month: "jan"} 
];

// 1. 用rollup完成聚合:按月份、日期分组,计算每日平均金额
const rolledUpData = d3.rollup(
  data,
  // 把amount转成数字后计算平均值
  group => d3.mean(group, item => Number(item.amount)),
  item => item.month, // 第一层分组键:月份
  item => item.day    // 第二层分组键:日期
);

// 2. 把嵌套Map转换成目标格式
const result = Object.fromEntries(
  Array.from(rolledUpData.entries()).map(([month, dayAvgMap]) => [
    month,
    // 把日期-平均值的Map转成指定的数组对象
    Array.from(dayAvgMap.entries()).map(([day, avg]) => ({
      day,
      avg_amount: avg.toString() // 转成字符串匹配你期望的输出格式
    }))
  ])
);

console.log(result);
// 输出正好是你要的:{"jan": [ {day:"mon", avg_amount:"4"}, {day:"tue", avg_amount:"2"}, {day:"wed", avg_amount:"2"} ]}

关键步骤解释

  • 转数字计算平均值:原始数据的amount是字符串类型,d3.mean处理字符串会得到NaN,所以必须用Number(item.amount)转成数字后再计算。
  • Object.fromEntries():把外层Map的键值对直接转换成普通对象的属性,比如把Map{"jan": ...}转成{"jan": ...}。
  • 内层Map转数组:用Array.from(dayAvgMap.entries())把日期和平均值的Map转成[day, avg]的数组,再用map把每个元素转换成你需要的{day, avg_amount}对象,最后把平均值转成字符串匹配期望的输出。

这样就能完美得到你想要的结果啦!

内容的提问来源于stack exchange,提问作者michszm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:29:19