如何用D3.js或JS工具按src和tgt分组计算var_a平均值?
嘿,这个需求其实用纯JavaScript或者D3.js都能轻松搞定,我给你两种方案参考:
方案1:纯JavaScript实现
不用依赖任何库,原生JS就能完成,思路是先通过键值对分组,再计算每组的平均值:
示例数据
先定义一个符合你需求的示例数组:
const data = [ { src: 9, tgt: 2, var_a: 10 }, { src: 9, tgt: 2, var_a: 20 }, { src: 9, tgt: 2, var_a: 30 }, { src: 9, tgt: 2, var_a: 40 }, { src: 6, tgt: 1, var_a: 50 } ];
实现步骤
- 创建分组映射:用
src-tgt的拼接字符串作为唯一键,把相同键的元素归为一组 - 遍历映射,计算每组的平均值
代码如下:
// 第一步:分组 const groups = {}; data.forEach(item => { // 生成唯一分组键 const key = `${item.src}-${item.tgt}`; // 如果键不存在,初始化空数组 if (!groups[key]) groups[key] = []; groups[key].push(item.var_a); }); // 第二步:计算平均值并整理结果 const result = Object.entries(groups).map(([key, values]) => { const [src, tgt] = key.split('-').map(Number); const average = values.reduce((sum, val) => sum + val, 0) / values.length; return { src, tgt, average }; }); console.log(result); // 输出结果: // [ // { src: 9, tgt: 2, average: 25 }, // { src: 6, tgt: 1, average: 50 } // ]
方案2:D3.js实现
如果你已经在使用D3,那用d3.rollup可以一步完成分组+聚合,非常高效:
代码实现
// 浏览器环境直接用全局d3对象,模块化环境需导入 import { rollup, mean } from 'd3-array'; const data = [ { src: 9, tgt: 2, var_a: 10 }, { src: 9, tgt: 2, var_a: 20 }, { src: 9, tgt: 2, var_a: 30 }, { src: 9, tgt: 2, var_a: 40 }, { src: 6, tgt: 1, var_a: 50 } ]; // 使用d3.rollup分组并计算平均值 const grouped = rollup( data, // 聚合函数:直接计算var_a的平均值 v => mean(v, d => d.var_a), // 分组维度:先按src,再按tgt,确保两者完全相同才会归为一组 d => d.src, d => d.tgt ); // 转换为易读的对象数组格式 const result = Array.from(grouped, ([src, tgtMap]) => Array.from(tgtMap, ([tgt, average]) => ({ src, tgt, average })) ).flat(); console.log(result); // 输出和纯JS方案一致的结果
说明
d3.rollup的第二个参数是聚合逻辑,这里用d3.mean省去了手动写reduce求和再取平均的步骤- 后面两个参数是分组的层级,先按
src再按tgt,确保只有两者同时匹配的元素才会被分到同一组 - 最后用
Array.from把D3返回的Map结构转换成普通对象数组,方便后续业务使用
两种方案都能完美满足你的需求,纯JS方案适合不想引入额外库的场景,D3方案则更简洁优雅,适合已经在使用D3的项目~
内容的提问来源于stack exchange,提问作者MeBex
相关产品推荐
相关产品推荐

