R 语言探索性分析入门:先看懂数据,再画对图
拿到一份新数据,第一反应往往是直接建模型、跑回归、出预测。但数据分析里最容易翻车的地方,恰恰在模型之前:数据里藏着缺失值、离群点、录错的单位,变量之间的关系也和想象的不一样。探索性分析做的就是这件事:在正式分析之前,先把数据看清楚。本文用 R 语言讲一套完整流程:先用 dplyr 看结构、算分布、找缺失值,再用 ggplot2 把分布与关系画出来。

本文的函数名与包名按 R 与 tidyverse 官方文档核实,核实日期 2026-11-09;标注“未核实”的地方是本文没有在官方页面逐项验证的细节。示例用 R 自带的数据集 mtcars 与 iris,复制代码就能跑,不需要另外准备数据。
探索性分析到底在探索什么
探索性分析要回答的问题很具体,只有四个:数据长什么样,有没有脏的地方,变量各自怎么分布,变量之间有没有关系。四个问题各有对应的工具,混在一起做很容易顾此失彼。
先说一个原则:探索阶段的目标是发现问题,不是证明结论。 某组数据的平均值很高,可能是少数几个极端值拉起来的。探索性分析的产出是一份“数据体检报告”,而不是最终结论。
第一步:装好工具,看清数据结构
R 语言里做探索性分析,最常用的两个包是 dplyr 与 ggplot2,都属于 tidyverse 包集合:dplyr 负责整理与汇总数据,ggplot2 负责画图。第一次使用前先安装,之后每次打开 R 都要加载。
1install.packages("tidyverse")
2library(tidyverse)
install.packages 只需要在第一次安装时运行一次,library 则每次新开 R 会话都要运行。只装 dplyr 与 ggplot2 也可以,效果一样(核实日期 2026-11-09)。
装好工具后,以 R 自带的 mtcars 为例,它记录了 32 款汽车的油耗、马力、重量等 11 个变量。
1head(mtcars)
2str(mtcars)
3summary(mtcars)
head 看前几行,str 看每一列的类型,summary 给每一列算最小值、四分位数、中位数、均值与最大值。三行跑完,你应该能回答:多少行多少列,每列什么类型,数值范围合不合理。如果出现明显离谱的数字,比如马力是负数,那就是数据录入有问题,先记下来。
dplyr 的 glimpse 把每列的类型与前几个取值横着排出来,列多时比 str 更好读。
1glimpse(mtcars)
第二步:找缺失值与重复值,先把脏数据挑出来
缺失值是探索阶段最常见的坑。R 用 NA 表示缺失值,很多汇总函数遇到 NA 会直接返回 NA,不报错也不提醒,结果悄悄变成空值。动手算任何统计量之前,先数一数每列有多少个缺失值。
1colSums(is.na(mtcars))
is.na 判断每个位置是不是缺失值,colSums 再按列加总。mtcars 本身没有缺失值,输出会全是零;换成自己的数据,这里就可能出现非零的数字。发现缺失值之后不要急着删:先看缺失集中在哪些列、哪些行,是随机缺失还是某类记录整批缺失,删与填的决定要留到正式分析时再做,探索阶段先记录。
第三步:单个变量怎么分布,一个一个看
搞清楚结构与缺失值之后,开始看每个变量自己的分布。数值变量与分类变量的看图方法不一样,选错图比不画图更容易误导自己。
数值变量先看直方图:把数值切成一段一段的区间,数每段里有多少个观测,一眼就能看出分布是集中还是分散,有没有离群点。
1ggplot(mtcars, aes(x = mpg)) +
2 geom_histogram(binwidth = 2, fill = "steelblue", color = "white")
这段代码画的是 mpg(每加仑英里数)的直方图。ggplot 设定数据与横轴变量,geom_histogram 负责画直方图,binwidth 控制每段区间的宽度。区间太宽会把细节抹平,区间太窄又全是毛刺,多试两个宽度再决定。读这张图时注意峰值落在哪一段,大多数观测集中在哪个范围,有没有远远落在主体之外的离群点,先记下来,不要顺手删掉。
分类变量看条形图,以 cyl(气缸数)为例,数一数每个类别有多少辆车。
1ggplot(mtcars, aes(x = factor(cyl))) +
2 geom_bar(fill = "steelblue")
geom_bar 会自动统计每个类别的数量,factor 把数值型的气缸数转成类别,避免它被当成连续数值处理。读条形图时只问一个问题:哪个类别最多,哪个最少。
第四步:分组汇总,用数字回答“哪组更高”
看完单个变量,接下来比较组与组之间的差别。dplyr 的 group_by 加 summarise 是做这件事的标准组合:先按某个变量分组,再在每组里算统计量。
1mtcars %>%
2 group_by(cyl) %>%
3 summarise(
4 数量 = n(),
5 平均油耗 = mean(mpg),
6 中位油耗 = median(mpg),
7 最高油耗 = max(mpg),
8 最低油耗 = min(mpg)
9 )
group_by 与 summarise 的组合可以叠加多个分组变量,比如按气缸数与变速箱类型同时分组,输出一张更细的汇总表。汇总表本身就是探索结果的一种,不必每张表都画成图。
第五步:两个变量有没有关系,用散点图与箱线图看
探索性分析的后半段是看变量之间的关系。两个数值变量之间,用散点图;一个分类变量加一个数值变量,用箱线图。
先看散点图:横轴放马力 hp,纵轴放油耗 mpg,每个点是一辆车。
1ggplot(mtcars, aes(x = hp, y = mpg)) +
2 geom_point()
读散点图时问三个问题:点是往上走还是往下走,是聚成一条带还是散得到处都是,有没有脱离主体的点。mtcars 这张图上,马力越大油耗越低,点大致沿着一条往下走的带分布,这是负相关的典型样子。但要记住探索阶段的原则:相关不是因果。 散点图只能说两个变量一起变化,不能说一个导致另一个。
把气缸数映射到颜色上,同一张图就多了一层信息。
1ggplot(mtcars, aes(x = hp, y = mpg, color = factor(cyl))) +
2 geom_point(size = 3)
不同气缸数的车是不是各自聚成一团,颜色一加上就看得出来。颜色别超过五六种,多了反而看不清。
再看箱线图:按气缸数分组,比较每组的油耗分布。
1ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
2 geom_boxplot(fill = "steelblue")
箱线图一根柱子顶上一个盒子:盒子中间的线是中位数,盒子的上下边是第一与第三四分位数,盒子外面伸出的线是大部分数据的范围,单独画在外面的点是离群值。读箱线图时先比较盒子中间线的位置,再比较盒子的长短,盒子越长说明这组内部差异越大,最后看外面的离群点。箱线图与分组汇总表是互补的:表给精确数字,图给整体感觉。
第六步:多组对比一次看完,用分面拆开
变量一多,图很快就不够放。ggplot2 的 facet_wrap 可以按某个分类变量把一张图拆成多张小图,排在一起比较。
1ggplot(mtcars, aes(x = hp, y = mpg)) +
2 geom_point() +
3 facet_wrap(~ cyl)
facet_wrap(~ cyl) 按气缸数拆出三张散点图,每张只画该组的车。分面图的读法是横向比较:三张小图的走势一样吗,哪张更分散。分面适合回答“这个规律在每个组里都成立吗”;如果某组的走势和其他组完全不同,那里往往藏着值得深挖的问题。
第七步:把探索结果写成一份体检报告
图画完了、表算完了,探索性分析还没结束:最后一步是把发现写下来。报告不需要长,一页就够,但要回答四个问题:数据的基本情况如何,数据质量如何,主要发现是什么,下一步建议是什么。每条发现后面附上对应的图或表,缺失值、离群点与可疑值登记在册即可。
写报告时注意一个分寸:探索阶段的发现都写成“看起来”,不写成“证明了”。 图上看到的现象是线索,不是结论;正式分析的任务,就是验证这些线索里哪些站得住。
什么时候可以停下来,去做正式分析
探索性分析没有标准答案式的完成标志,但有三个信号说明可以收尾了:第一,你能用一两句话说清这份数据的结构与主要问题;第二,缺失值、离群点与可疑值都已经登记在册,知道它们在哪、有多少;第三,你手里已经有三到五张关键的图,能回答这份数据最核心的几个问题。到了这一步,就可以带着体检报告去做建模与检验了。反过来,如果某个变量的分布你还说不清楚,或者图上出现了一个完全解释不了的异常点,别急着往下走:探索阶段多花半小时,正式分析可能少返工半天。