ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Dataset.js 派生数据集实战:groupBy、countBy 与 movingAverage 让数据变换更智能

Dataset.js 派生数据集实战:groupBy、countBy 与 movingAverage 让数据变换更智能

【免费下载链接】dataset

JavaScript library that makes managing the data behind client-side visualisations easy

项目地址:https://gitcode.com/gh_mirrors/datas/dataset
点击查看免费下载

Dataset.js(Miso.Dataset)是一个帮助前端开发者轻松管理可视化数据的 JavaScript 库,负责数据的加载、解析、排序、过滤与查询。其中最实用的能力之一是派生数据集(Derived Dataset):通过groupBy、countBy和movingAverage三个方法,你可以从原始数据一键生成汇总统计、频次计数和滑动平均,并且原始数据更新时结果会自动重算。本文带你快速上手这三项数据变换功能。

什么是派生数据集?

派生数据集本质上是一个"计算出来的子数据集"。它:

  • 保持对父数据集的引用,记录生成它的方法
  • 拥有独立的_id主键和_oids列(保存参与计算的原行 id)
  • 行为和普通数据集完全一样,可以继续用where、rows、toJSON等 DataView 接口查询

核心实现位于 src/derived.js,所有派生方法都挂载在Dataset.DataView原型上,所以 Dataset 和 Derived 都能调用。

准备工作:创建并加载一个数据集

下面的示例基于项目测试用例 test/unit/derived.js 中的数据:

var ds = new Miso.Dataset({ data : { columns : [ { name : "state", type : "string", data : ["AZ", "AZ", "AZ", "MA", "MA", "MA"] }, { name : "count", type : "number", data : [1, 2, 3, 4, 5, 6] }, { name : "anothercount", type : "number", data : [10, 20, 30, 40, 50, 60] } ] }, strict: true }); _.when(ds.fetch()).then(function () { // 数据集就绪,可以开始变换 });

💡fetch是异步的,变换操作请放在success回调或 Promise 回调中执行。

groupBy:按列分组并自动汇总

groupBy(byColumn, columns, options)按指定列把行"分箱",并对指定列做聚合。参数说明:

参数作用
byColumn分组依据的列名,如"state"
columns需要聚合的列名数组
options.method聚合函数,默认求和,可传入任意function(arr)
options.preprocess分组值归一化函数,适合"时间分箱"等非精确相等的分组

基本用法——按州汇总两列数值:

var grouped = ds.groupBy("state", ["count", "anothercount"]); // state: ["AZ", "MA"] // count: [6, 15] // 1+2+3 / 4+5+6 // anothercount: [60, 150] // 10+20+30 / 40+50+60

官方示例见 examples/api/dataview/group-by.js。

自定义聚合方法

默认求和不够用?传入自己的method即可,比如求乘积:

var grouped = ds.groupBy("state", ["count"], { method: function (arr) { return _.reduce(arr, function (memo, num) { return memo * num; }, 1); } });

preprocess:按"派生值"分组

当分组键需要先做转换(比如把日期归到某一年),可以用preprocess对每个分组值做归一化:

ds.groupBy("state", ["count"], { preprocess: function (state) { return state + state; } // 分组结果变为 ["AZAZ", "MAMA"] });

这一技巧常用于按时间粒度(年/月/周)对时间戳列分箱统计。

countBy:一行代码统计取值频次

countBy(byColumn)会返回一个包含两列的派生数据集:原列 +count列,直接给出每个取值出现的次数。

以测试数据['a','b','a','a','c','c',null,'a','b','c']为例:

var counted = ds.countBy("category"); // category: ["a", "b", null, "c"] // count: [4, 2, 1, 2]

它的亮点:

  • ✅ 能统计任意类型,包括null、对象、数组(测试用例 "counting a mess")
  • ✅ 时间列会被正确解析后比较,同一天的两条记录会合并计数
  • ✅ 结果仍是数据集,可继续rows/where筛选

完整示例见 examples/api/dataview/count-by.js。做词频、类别分布图时,这一步省去了大量手写循环。

movingAverage:滑动平均抹平波动

movingAverage(columns, size, options)对指定列计算滑动平均,窗口大小为size:

var ds = new Miso.Dataset({ data : { columns : [ { name : "A", data : [1,2,3,4,5,6,7,8,9,10], type : "numeric" }, { name : "B", data : [10,9,8,7,6,5,4,3,2,1], type : "numeric" } ] }, strict : true }); _.when(ds.fetch()).then(function () { var ma = this.movingAverage(["A"], 3); // A: [2, 3, 4, 5, 6, 7, 8, 9] 每行是连续 3 个值的平均 // ma.length === 10 - 3 + 1 = 8 });

几个关键行为(来自 test/unit/derived.js 中的 "Moving Average" 模块):

  • 📐 结果行数 = 原行数 −size+ 1,因为前size-1行凑不满窗口
  • 📋未参与平均的列会被原样保留(如B、C列直接复制),方便对照绘图
  • 🔄 默认聚合函数是mean,也可通过options.method换成方差等,如{ method : _.variance }
  • 🚫 不能对 id 列求滑动平均,否则直接抛出错误
  • 🔗_oids列保存了每个窗口对应的原行 id 数组,便于回溯

股票 K 线加均线、传感器数据平滑、销量趋势分析——都是它的典型场景。

真正的杀手锏:派生结果自动同步

如果父数据集开启了实时同步(sync: true),派生数据集会自动重新计算,无需手动刷新:

var ds = new Miso.Dataset({ data : getData(), strict : true, sync : true }); _.when(ds.fetch()).then(function () { var grouped = ds.groupBy("state", ["count", "anothercount"]); ds.add({ state : "MN", count : 100, anothercount : 100 }); // grouped 立刻变为 ["AZ", "MA", "MN"],无需任何手动操作 });

测试用例覆盖了完整的实时场景:

  • add新类别 → 新增分组行
  • update修改分组键 → 该行自动迁移到新分组
  • remove删除行 → 汇总值即时扣减
  • movingAverage在源数据update后同样自动重算

实现原理很简单:派生数据集在父数据集上subscribe("change", ...),事件触发时重新执行生成它的func并广播change(见 src/derived.js 中Dataset.Derived构造函数与_sync方法)。做实时看板时,你只需把派生数据集接到图表上,数据变了图就变了。

小结:三种变换各适合什么场景

方法一句话定位适用场景
groupBy分组 + 聚合(默认求和,可自定义)分类汇总、按时间分箱统计
countBy统计每列取值频次词频、类别分布、饼图数据
movingAverage窗口滑动平均趋势平滑、均线叠加

三者的共同优势:结果是标准数据集,可继续用where、sort、toJSON二次加工;开启sync后还能实时联动。相关功能入口汇总:

  • 核心实现:src/derived.js
  • 官方示例:examples/api/dataview/group-by.js、examples/api/dataview/count-by.js
  • 单元测试(含完整用法):test/unit/derived.js
  • 项目说明:README.md

掌握groupBy、countBy和movingAverage,你就能用 Dataset.js 把原始数据"变换"成图表直接可用的形态——数据管理从此更智能。

【免费下载链接】dataset

JavaScript library that makes managing the data behind client-side visualisations easy

项目地址:https://gitcode.com/gh_mirrors/datas/dataset
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进