在前端开发中,经常需要处理海量数据,并统计出某个字段的频次分布情况,比如用户年龄分布、商品价格区间分布等等。如果手动计算这个分布,难度很大,效率也很低。而 npm 包 compute-histogram
可以帮助我们快速处理这类问题。
1. 安装
使用 npm 安装 compute-histogram
:
npm install compute-histogram
2. 使用
2.1. 基本用法
-- -------------------- ---- ------- ------ ------------------ ---- ------------------- ----- ---- - --- -- -- -- -- -- --- ----- ------- - - ------- --- --- -- ------ --------- -- -- ------ -- ----- --------- - ---------------------- --------- -- ------ ----------------------- -- ---- ----- --- -- -- --- ------- --- -- -- --- --------- - -
以上示例中,我们定义了数据范围 [1, 4]
,即数据中可能出现的最小值为 1,最大值为 4(注意,这里只定义了可能出现的范围,而不是所有数据中实际出现的范围)。binWidth
定义了每个区间的宽度,默认值为 1。
computeHistogram
函数的第一个参数为一个数组,表示原始数据。第二个参数为一个选项对象,用于定义数据范围和区间宽度。computeHistogram
函数返回一个对象,包含三个属性:
bins
:表示每个区间的起始点(不包括结束点),是一个数组。counts
:表示每个区间的数据条数,是一个数组。binWidth
:表示区间宽度。
2.2. 简单实例
接下来我们通过一个简单实例来演示 compute-histogram 的用法。数据集为 NBA 历史得分数据,每个数据对象包含球员姓名、出场次数和总得分:
-- -------------------- ---- ------- ----- ---- - - - ----- ------- -------------- ------ ----- ---- ----- -- - ----- ----- -------- ------ ----- ---- ----- -- - ----- ------- ------- ------ ----- ---- ----- -- - ----- ----- -------- ------ ----- ---- ----- -- - ----- -------- -------- ------ ----- ---- ----- -- - ----- ----- ---------- ------ ----- ---- ----- -- -- --- --
我们的目标是统计这些球员的总得分分布情况,这里我们以 1000 点为一个区间:
const options = { domain: [0, 50000], binWidth: 1000, }; const { bins, counts } = computeHistogram(data.map(d => d.pts), options); console.log(bins, counts); // 输出:[ 0, 1000, 2000, ..., 49000, 50000 ] [ 0, 0, 0, ..., 0, 1 ]
这里我们使用了数组的 map
方法将 data
中的 pts
属性映射为一个数组 ptsData
,以供 computeHistogram
函数使用。
结果显示,只有一位球员的总得分超过 33000 点,这位球员是 Kobe Bryant。得分 1000-2000 点的球员有零位,得分在 2000-3000 点的球员有零位……直到得分在 49000-50000 点有一位,也就是 Kobe Bryant。这个结果让我们了解到不同得分段上一共有多少位球员。
2.3. 复杂实例
刚才我们简单统计了 NBA 球员的得分分布。这个分布图是以整数出现次数为纵轴的柱状图,我们称之为频数分布图。频数分布图虽然可以告诉我们分布情况,但很难根据分布图得出百分比分布情况。如果要求出某个值的百分比分布情况,需要将所有 bins 中小于该值的频数进行求和。这时候,就需要计算累计频数分布图。累计频数分布图是以百分数出现次数为纵轴的折线图。
那么怎么计算累计频数分布图呢?说白了就是将频数依次相加,所得的新数组就是累计频数。接下来我们就来计算累计频数分布图。
在之前的代码基础上,我们添加如下代码,将一个长度为 counts.length
的数组 cdf
的值设为该数组前 i 个元素之和:
let cdf = [counts[0]]; for (let i = 1; i < counts.length; i++) { cdf[i] = cdf[i - 1] + counts[i]; }
然后将纵轴改为百分数即可:
const totalCount = cdf[cdf.length - 1]; cdf = cdf.map(v => v / totalCount * 100);
完整代码如下:
-- -------------------- ---- ------- ----- - ----- ------ - - --------------------------- -- ------- -------- --- ------- --------- ------- --- --- - ------------ --- ---- - - -- - - -------------- ---- - ------ - ----- - -- - ---------- -- ---- - ----- ---------- - -------------- - --- -- --- --- - --------- -- - - ---------- - ----- -- ------ ----------------- ----- -- ------ ----- ----- ---- ------ ------ - -- -- -- ---- ------------------ --- -
最终结果表明,总得分达到 33000 点的球员,占总人数的 15% 左右。
3. 总结
至此,我们已经掌握了 compute-histogram
的使用方法。在实际开发中,本文中的示例代码同样适用于处理大多数数据分布问题。当然,还有一些细节问题需要注意,在使用过程中一定要注意选择合适的数据范围和区间宽度。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/600671d530d0927023822b37