前段时间双十一的数据被网传造假,李永乐老师就科普了一期用 本福特定律 来简单数据校验。具体的科普验证方式点击教程链接。
最近一直关注着武汉肺炎的疫情数据,闲来无事就想拿这些数据做点本福特定律的实操。(加上很久没写 JavaScript 了,练练手)。
什么是本福特定律
本福特定律(台湾作班佛定律)(英语:Benford's law),说明一堆从实际生活得出的数据中,以1为首位数字的数的出现概率约为总数的三成,接近直觉得出之期望值1/9的3倍。推广来说,越大的数,以它为首几位的数出现的概率就越低。它可用于检查各种数据是否有造假。—— 维基百科
自然生活中有许多数据,例如各个国家的人口、GDP、国土面积,视频网站的播放量、元素的半衰期等自然界的数据,以 1 为首的数字出现概率约为30%:
- 李永乐老师的视频播放量:29.3%
- 国家地区人口:28.5%
- GDP:30.5%
- 国土面积:27.3%
- 斐波那契数 29.2%

实操
提取数据
丁香园新型冠状病毒肺炎疫情实时动态 提取数据(截止北京时间1-26 11:27):每个县市提交的数据是应该是相对独立的,肉眼观察数据的跨度从一位数到三位数不等。但省份的数据是根据县市累加的数值,就不计算在样本里。
通过观察 html 的结构得知县市的疫情确诊数据都属于 .areaBlock2___27vn7 .subBlock2___E7-fW CSS 类名下,用 querySelectorAll 获取所有 DOM 节点数据,提取数字。

拿到数据之后简单对比一下提取出来的数据有没有明显出错。正确的话进行下一步操作。
计算以 N 为首位数字的概率


完整代码如下:
var data = document.querySelectorAll('.areaBlock2___27vn7 .subBlock2___E7-fW')
var array = []
var result = {}
data.forEach(x => array.push(x.innerText))
// 以下几个省因为没有细分县市区导致有遗漏:上海、天津、香港、澳门、台湾,影响不大,也可以手动塞进去
// 我在这里就没有插入了
// array.push(...['40', '13', '5', '5', '3'])
result = array.reduce((prev, i) => (prev[i[0]]++ || (prev[i[0]] = 1), prev), {});
Object.keys(result).map(i => result[i]/array.length)表格计算/绘制图表
最后拿到9个数字的概率,和本福特定律进行比较。在Google 表格(一般的 Excel 软件也带这类函数、绘图表功能)里绘制图表并进行计算一些方差值。


A:以 N 为首位数字
B:本福特定律的概率
C:疫情确诊数据得出的概率
D:B-C 之间的差值绝对值
最后通过图表数据可以看到两条线基本倾向大致一致,以1为首位的数字概率相差幅度最大, 0.064。因为对数据分析没什么研究,权当抛砖引玉。
欢迎指正 JavaScript 代码~
