← 首页
New Zealand (NZ) — Secondary (Years 9–10); learner level: Years 9–10

数据整理与可视化:从一堆凌乱的记录到一张可信的图

同一批数据,只要把纵轴起点从 0 改成 90,5 个百分点的差距就能看起来像 5 倍。数据整理与可视化既是让你把故事讲清楚的工具,也可能是别人用来骗你的武器——这一页教你把两者都握在手里。

一、数据不是数字:先把变量认清楚

假设你在奥克兰(Auckland)的一所中学做了一项调查,问了 60 名 Year 9 学生两个问题:「你今天怎么来上学?」和「路上花了多少分钟?」拿回来的结果长得像这样:

  • 通勤方式:步行、公交、骑车、家长开车、步行、公交……
  • 通勤时间:12、25、8、40、18、14、22……

这样一堆没有加工过的记录,叫原始数据(raw data)。在动手算任何东西之前,先要认清三样东西:

  • 观测单位(individual / case):被记录的对象。这里是每一名学生。
  • 变量(variable):在每个对象身上记录下来的特征。这里是「通勤方式」和「通勤时间」。
  • 数据(data):所有观测单位在某个变量上取到的值的全体。

为什么「类型」这一步不能跳过?因为你不能对「步行」求平均。数据的类型决定了哪些整理方式、哪些图形、哪些统计量是合法的。常见的分类是这样的:

graph TD
  A["变量 variable"] --> B["类别型 categorical:取值是标签"]
  A --> C["数值型 numerical:取值是数字"]
  B --> B1["名义型 nominal:通勤方式、血型"]
  B --> B2["有序型 ordinal:满意度、年级等级"]
  C --> C1["离散型 discrete:兄弟姐妹人数、每周去超市次数"]
  C --> C2["连续型 continuous:通勤时间、身高、下午三点的气温"]

换成新西兰(New Zealand)日常生活中的例子,你会更容易记住这几类:

  • 类别型(categorical):取值是标签。其中「满意度:很不满/一般/满意/很满意」有自然的先后顺序,叫有序型(ordinal);「通勤方式」「最喜欢的橄榄球队」没有顺序,叫名义型(nominal)
  • 数值型(numerical) 中的离散型(discrete):取值是一个一个分开的数,中间没有别的东西,比如「你有几个兄弟姐妹」。
  • 数值型 中的连续型(continuous):理论上可以取到任意精度,比如通勤时间(15.3 分钟、15.34 分钟都说得通)、身高、气温。

一个很实用的判据是问自己两句话:「能不能算出一个有意义的平均?」「能不能说出一个有意义的差?」 通勤时间可以平均,也可以说「多花了 7 分钟」;通勤方式两样都不行,所以它只能是类别型。

还有一点容易忽略:类型不只由问题决定,也由你怎么记录决定。

同一个问题「你最近一周运动了几次?」,可以记录成哪几种变量类型?
  • 记录具体次数(0、1、2、3……):离散数值型
  • 记录成「从不/1–2 次/3–4 次/5 次以上」:有序类别型——有顺序,但类别之间的距离不一定相等。
  • 改问「每周运动多少小时」并允许填 3.5:连续数值型

所以拿到一张数据表时,第一件事是看清表头是怎么记录的,而不是急着画图。

二、整理:频数表与分组

整理的第一步,是把「一堆记录」变成「一张能一眼看懂的清单」。

如果变量是类别型的,最有效的办法就是数一数每一类出现了多少次。这个次数叫频数(frequency),数数的过程可以先用划线记数(tally)。把类别和频数排在一起,就是一张频数表(frequency table)

通勤方式 频数 相对频率 饼图对应的圆心角
步行 9 0.15 54°
骑车 6 0.10 36°
公交 24 0.40 144°
家长开车 21 0.35 126°
合计 60 1.00 360°

右边两列其实是同一件事的两种说法:相对频率(relative frequency)告诉你「占多大比例」,圆心角告诉你「如果要画饼图,这一块该切多大」。为什么一定要有相对频率?因为如果另一所学校只调查了 30 人,其中 12 人坐公交,你拿 24 和 12 直接比较是不公平的;比较 0.40 和 0.40 才公平。

数值型变量怎么办?如果取值不多(比如兄弟姐妹人数只有 0、1、2、3),直接按取值列频数表就行。但通勤时间有 60 个几乎各不相同的数字,一个一个数毫无意义——于是我们把数值轴切成若干首尾相接的区间,每个区间叫一个组(class),区间的宽度叫组距(class interval / bin width),落在某一组里的观测个数就是这一组的频数。

分组有几条经验规则:

  1. 不重不漏:组与组首尾相接,不重叠也不留缝。
  2. 组距一致:宽度相同,柱子的高度才可以直接比较。
  3. 组数取 5–12:太少会把分布压成一块砖,太多会把结构碎成噪声。
  4. 边界取整齐的数(0、10、20、30 分钟),并明确约定边界上的数据归哪一组;常用左闭右开 :正好 10 分钟的学生归入 ,不归入

这里有一条要老实承认的原则:分组会丢信息。一旦把 12 分钟和 19 分钟塞进同一个 ,你就再也看不出它们其实差 7 分钟。所以数据量不大时,最好把保留每个数据真实位置的点图(dot plot)和直方图一起看。下面这个实验台就是让你亲手体会这一点的。

演示 1 · s2·s2-demo
KEY POINT
组距是一个选择,不是事实

同一批数据,在不同组距下可以呈现出完全不同的「形状」:

  • 组距太大(比如 60 个通勤时间只用 2 根柱子):分布被压扁,什么都看不出来。
  • 组距太小(柱子高度大多是 0 和 1):锯齿状的随机起伏会被误读成「结构」。

正确做法是用两三个不同组距各画一次,只有当结论在多个组距下都成立时,才可以放心写进报告。如果结论随组距变化而翻转,就诚实地写:「该结论依赖于分组方式」。

QUIZ
某校调查了 45 名学生「放学后是否参加运动队」。其中打橄榄球(rugby)的学生有 9 人。这个类别的相对频率是多少?

相对频率 = 频数 ÷ 观测总数 = 9 ÷ 45 = 0.20,也就是 20%。选 5 是把除法算反了(总数 ÷ 频数);0.45 把总数当成了分子;0.09 是把 9 误当成了百分数。

三、选图:让图形匹配数据的类型

任何一张统计图,本质上都是把数字「映射」成视觉特征:位置、长度、角度、面积、体积、颜色深浅。而人眼判读这些特征的精度是有高低顺序的:

位置(数轴上的点)≈ 长度(柱子的高)> 角度(扇形)> 面积 > 体积 > 颜色深浅

这条顺序解释了为什么点图、直方图、条形图通常最可靠,而 3D 饼图几乎总是最差的:读者要用被透视扭曲的角度去估计比例。所以选图时先看变量类型,再看你想让读者回答哪个问题

graph TD
  Q["你要显示什么?"] --> A["一个类别型变量的分布"]
  Q --> B["一个数值型变量的分布"]
  Q --> C["两个数值型变量之间的关系"]
  Q --> D["某个量随时间的变化"]
  A --> A1["条形图 bar chart;类别很少时可用饼图 pie chart"]
  B --> B1["点图 dot plot(数据少)/直方图 histogram(数据多)/箱线图 box plot(要比较多组)"]
  C --> C1["散点图 scatter plot"]
  D --> D1["折线图 line graph(时间间隔等距)"]

条形图(bar chart)——类别型变量:每一类一根柱子,柱与柱之间留空隙,高度表示频数或百分比。把柱子按高低排序,读者比较起来会快很多。

直方图(histogram)——数值型分组数据:横轴是连续的数值区间,柱与柱相接,因为区间之间没有间断。它最擅长显示分布的形状:左右对称(symmetric)、向右拖出长尾的右偏(right-skewed)、出现两个峰的双峰(bimodal)。注意:直方图不能用来画类别型数据——「步行」和「公交」之间没有中点,接不起来。

点图(dot plot)——数据量不大时,每个观测画一个点,堆在数轴上。它保留每个数据的真实位置,最适合「看见原始数据」。

饼图(pie chart)——只在一种情况下有用:显示一个整体被分成几部分,而且类别很少(4–6 个)、占比差别明显。类别一多、差别一小,扇形角度就无法辨认了,这时换成条形图几乎总是更好。另外,气温、成绩这类不能相加成整体的量根本不能用饼图。

折线图(line graph)——横轴是时间且间隔一致时,用线段连接相邻时间点来显示趋势。前提是数据确实连续、没有大段缺失,否则线段会「编造」出一段不存在的上升或下降。

散点图(scatter plot)——两个数值型变量,每个观测是一个点 。用它看关系: 增大时 也增大叫正相关(positive correlation),反过来叫负相关(negative correlation),看不出规律叫无相关;还要留意非线性的形状(比如先升后降),一条直线会把它掩盖掉。

箱线图(box plot)——用五个数概括一个数值型变量的分布,最适合并排比较好几组数据(例如四个班级的通勤时间),细节见第四节。

无论选哪种图,一张负责任的图必须自带这四样东西:

  • 标题,说明「这张图在讲什么」;
  • 两条轴各自的名字与单位(分钟?次数?百分比?纽元?);
  • 必要的刻度值,而且纵轴是否从 0 开始要能一眼看出
  • 数据来源与样本量(例如:来源:本校 Year 9 通勤调查,n = 60)。

新西兰统计局(Stats NZ)等机构发布的图表都遵循这套规范,因为缺了任何一项,读者就无法独立判断你的结论是否站得住。

演示 2 · s3·s3-demo
QUIZ
你想显示惠灵顿(Wellington)某地 12 个月的平均气温变化,哪一张图最合适?

月份有固定顺序,读者关心的是「升还是降、什么时候最冷」,折线图用线段把这个顺序直接画了出来。选项 0 逻辑不成立:气温不能相加成 100%,画饼图没有意义。选项 3 的条形图虽然能看出谁高谁低,但打乱时间顺序后就看不出季节的起伏节奏了。散点图倒是可以用来研究「气温与某量」的关系,但这里只有一个随时间的变量。

四、中心与离散:用很少的几个数把分布说清楚

整理一批数值型数据时,最常要回答两个问题:「数据大致在哪儿?」和「数据散得有多开?」前者叫中心(centre),后者叫离散程度(spread)。只报中心不报离散,等于只说了一半。

三个常用的中心量:

  • 平均数(mean):所有数据加起来除以个数。它是数据的「平衡点」——每个数据与平均数的差(偏差)加起来正好为 0。
  • 中位数(median):把数据从小到大排好,位置正中的那个数;若个数是偶数,取正中两个数的平均。
  • 众数(mode):出现次数最多的值。它是唯一对类别型变量也适用的中心量(例如「最常被选中的通勤方式是公交」)。

什么时候用哪一个? 关键要看数据里有没有离群值(outlier)——明显远离其他大多数观测的值。

平均数把每一个数据都算了进去,这既是优点也是弱点:它会被长尾拉走。看这 10 名学生的每周运动时长(小时):

平均数是 10 小时,可没有一个学生接近 10 小时;中位数是 小时,一听就像「典型学生」。那个 61(也许是校队运动员,也许是记录时多打了一个数字)把平均数拽向了它自己。这就是为什么新西兰的房价与收入报告常常报中位数:少数几百万纽元(NZD)的豪宅会把平均数抬得离普通家庭非常远。

离散程度常用的量:

  • 极差(range) = 最大值 − 最小值。算得快,但完全由两个极端的值决定,很脆弱。
  • 四分位数(quartiles):把排序后的数据四等分, 是第 25% 位置的数, 就是中位数, 是第 75% 位置的数。
  • 四分位数间距(interquartile range, IQR) :中间一半数据的宽度,不受两端极端值的影响。

五数概括(five-number summary):最小值、、中位数、、最大值——这五个数正好画成一张箱线图(box plot):箱子的两端是 ,箱内横线是中位数,两端的须伸到 1.5 倍 IQR 范围内最远的观测,超出这个范围的点单独画成离群值。

提醒一句:不同教材和软件对四分位数的取法不完全相同(「含中位数」与「不含中位数」两种惯例),小数点后会出现微小差别。重要结论通常不受影响,但报告时要说明你用的是哪一种。

为什么离散和中心一样重要? 两个班某次数学测验的平均分都是 65 分,但 A 班的分数集中在 60–70 分之间,B 班一半学生 30 分、一半学生 100 分。教学上的含义完全不同:A 班需要一个统一的推进节奏,B 班需要分层辅导。只看平均分,你什么也看不出来。

(同样的道理还有一句老话:平均水深 1 米的河,一样能把人淹死。)

一句话的选用规则:分布大致对称、没有离群值 → 用平均数配极差或标准差;分布偏斜或有离群值 → 用中位数配 IQR。 报告时把中心量和离散量一起给出,才算对分布负责。

演示 3 · s4·s4-demo
QUIZ
10 名学生的每周运动时长(小时)是:2, 3, 3, 4, 4, 5, 5, 6, 7, 61。要描述「典型学生每周运动多久」,下面哪个说法最合适?

平均数 10 小时被 61 拉高了,没有一个学生接近它,用它描述「典型」会严重误导。中位数 4.5 小时更可靠。选项 2 的极差描述的是离散程度,不是中心位置,而且它同样被 61 支配。选项 3 也不成立:这组数据的众数根本不唯一(3、4、5 都出现两次),而且「典型水平」本来就应该用中心位置的量来回答。完整、负责任的报告应该是:中位数约 4.5 小时,IQR 约 2.5 小时,并说明存在一个 61 小时的离群值。

五、图会骗人:可视化中的陷阱与自保

数据可视化既是工具,也可以是武器。下面清单里的每一种手法,在真实的新闻、广告和政治宣传中都出现过。

先记住最有用的一条区分:

  • 比较「长度」的图(条形图、直方图):纵轴必须从 0 开始。 因为读者是在比长度,截断纵轴会让长度之比与数值之比不再一致。
  • 比较「变化」的图(折线图):允许不截断纵轴,但必须在图上明确标出起点。因为这时读者关心的是坡度和转折,而不是绝对长度。

这条区分之所以关键,是因为很多人把「折线图可以截断」的习惯错误地搬到了条形图上。

常见的陷阱:

  1. 截断纵轴(truncated axis):条形图纵轴从 95 开始,96 与 91 的两根柱子看起来可以差好几倍。
  2. 面积或体积夸大:用一个小图标代表 10 人,再用一个「宽两倍、高两倍」的图标代表 40 人——面积变成了 4 倍,读者的眼睛被骗了两次。
  3. 3D 效果与透视:3D 饼图里靠前的扇形在透视下显得更大,角度再也无法可靠估读。
  4. 双纵轴(dual axis):给两条曲线各自拉伸刻度,几乎任何两组数据都能被摆成「看起来一起涨」。
  5. 挑选时间段:只画对自己有利的年份区间,把不利的部分截掉。
  6. 不一致的组距:直方图里有一组的宽度是其他组的两倍,高度却按频数画——柱子的面积就不再与频数成比例。
  7. 没有基数:「增长了 200%」听起来很多,可从 2 例到 6 例也正好是 200%。
  8. 抽样偏差(sampling bias):图再漂亮,如果问卷只发在运动队的群里,结论就只能适用于运动队成员。图不会修好坏数据。

最后还有一种最隐蔽的误导,它甚至不算「画图技巧」,却天天出现:用平均数掩盖整个分布。 第四节里两个平均分都是 65 的班级,就是最好的例子。

演示 4 · s5·s5-demo

作为读者,看到一张图时问自己四个问题:

  1. 纵轴的起点在哪?单位是什么? 柱子的长度与数值成比例吗?
  2. 样本是谁、有多少(n = ?)? 这个结论能推广到谁身上?
  3. 绝对数量是多少? 百分比之外的原始数字,常常会改变整个故事。
  4. 换一种画法,结论还在吗?(换个时间段、换成中位数、换成条形图再试一次。)

作为作者,准则更简单:画一张你愿意让别人用同一份数据来反驳你的图。 用真实的刻度、说明组距、给出 n 和数据来源,并主动说出结论的局限。

QUIZ
一张条形图比较两所学校的 NCEA(National Certificates of Educational Achievement,新西兰国家教育成就证书)Level 1 数学达标率:A 校 96%,B 校 91%。图中 A 校的柱子看起来有 B 校的 5 倍高。最可能的原因是什么?

柱子表达的是长度,而长度之比必须与数值之比一致。当纵轴从 90(或任意非 0 值)开始时,96 与 91 的柱长之比会变成 6 : 1,5 个百分点的小差异就被画成了巨大差异。正确的改法是把纵轴拉回 0(此时两柱几乎一样高),或者干脆用点图、直接标数字。选项 2 不成立:饼图的角度在类别接近时同样难以分辨,再叠上 3D 透视只会更糟。样本量也不会让柱子自动变高。

六、总结:把一次数据整理走完一个循环

把前面五节串起来,你做的其实是同一件事,一遍又一遍——新西兰的课程里常把这个循环叫做统计调查循环(statistical enquiry cycle),用它的五个英文步骤首字母简称 PPDAC

graph TD
  P["问题 Problem:我们到底要回答什么?"] --> Pl["计划 Plan:调查谁、记录哪些变量、怎么记录?"]
  Pl --> D["数据 Data:收集、清理、编码(类型在这里定型)"]
  D --> A["分析 Analysis:频数表、分组、选图、中心与离散"]
  A --> C["结论 Conclusion:用数据说话,并说明局限"]
  C --> P

这一页走下来,你的工具箱里有:

  1. 认变量:类别型(名义/有序)还是数值型(离散/连续)?类型决定哪些操作是合法的。
  2. 整理:类别型 → 频数表与相对频率;数值型 → 分组与频数表,并且牢记分组会丢信息。
  3. 选图:一个类别变量 → 条形图;一个数值变量 → 点图/直方图;两个数值变量 → 散点图;随时间变化 → 折线图;需要比较多组 → 箱线图。
  4. 描述:中心(平均数/中位数/众数)+ 离散(极差/IQR)。分布偏斜或有离群值时,优先用中位数配 IQR。
  5. 反思:纵轴起点、单位、样本量、绝对数量——这张图有没有在骗我?

下面这段代码把其中好几步自动化了:它从一列原始数据生成分组频数表、算出五数概括与 IQR,并自动标出离群值。你可以把数据换成自己班的调查结果。

从原始数据到频数表与五数概括
import statistics as st

times = [8, 25, 15, 40, 12, 18, 22, 9, 31, 17, 26, 14, 20, 35, 11]

# 1) 分组频数表:组距 10 分钟,区间为 [10k, 10k+10)
groups = {}
for t in times:
    lo = t // 10 * 10
    groups[lo] = groups.get(lo, 0) + 1

for lo in sorted(groups):
    print(f"[{lo:>2},{lo + 10:>2})  {'#' * groups[lo]} {groups[lo]}")

# 2) 五数概括与 IQR
q1, med, q3 = st.quantiles(times, n=4, method="inclusive")
iqr = q3 - q1
print("min, max   =", min(times), max(times))
print("Q1, median, Q3 =", q1, med, q3)
print("mean = " + str(round(st.mean(times), 2)) + "   IQR = " + str(iqr))

# 3) 用 1.5 x IQR 判据标出离群值
low, high = q1 - 1.5 * iqr, q3 + 1.5 * iqr
outliers = [t for t in times if t < low or t > high]
print("outliers =", outliers)
KEY POINT
一句话带走

数据整理与可视化不是「把数字画得漂亮」,而是一条链:

问题 → 变量类型 → 整理 → 图形 → 描述 → 反思

链条上任何一环偷懒,结论都会松动。反过来,只要每一环都交代清楚(用哪种组距、n 是多少、纵轴从哪里开始、中位数还是平均数),你的图就不只是好看,而是可信

继续探索