R语言描述性统计实战:从summary到自定义函数与可视化

发布时间:2026/10/29 4:38:59

R语言描述性统计实战:从summary到自定义函数与可视化 简介这份PDF资料面向R语言初学者与数据分析入门者系统梳理描述性统计分析的常用方法帮助读者快速掌握从基础统计量到分组分析与可视化的完整流程。内容覆盖summary()、sapply()等内置函数偏度与峰度自定义函数Hmisc、psych包的describe()函数以及aggregate()、by()、doBy包的summaryBy()分组统计并借助ggplot2绘制直方图与箱线图直观呈现数据分布。资源包共1个PDF文件约98KB篇幅精炼、代码示例完整便于随查随用。已有553人学习适合希望用R完成数据探索、为后续建模打基础的读者参考。1. 描述性统计不是跑个 summary 就完事一份能直接复用的 R 脚本包很多人第一次在 R 里做描述性统计都是summary(df)一把梭看到最小值、最大值、四分位数就以为摸清了数据底细。真到建模或者写报告时才发现均值被极端值拉飞、缺失值悄悄吃掉样本量、分组之后各组的偏度方向完全相反——这些summary()根本不会提醒你。这份资源围绕 R 语言描述性统计的完整链路展开从内置函数到自定义偏度峰度、从Hmisc/psych两个 describe 到分组聚合、再到ggplot2出图代码示例都是能直接粘进 RStudio 跑的。适合刚接手一份陌生数据集、需要快速产出数据画像的从业者也适合想把统计口径固定成模板、避免每次重复造轮子的熟手。下面按“先立口径、再上代码、最后避坑”的顺序拆。2. 先把统计口径立住summary、sapply 与自定义函数的取舍描述性统计最容易翻车的地方不是函数不会用而是口径不统一。同一份数据A 用summary()报均值B 用sapply()报标准差C 自己写了个偏度公式三个人算出来的峰度能差出一个量级。所以动手之前先把要算哪些量、缺失值怎么处理、分母用 n 还是 n-1 定下来比急着敲代码重要得多。2.1 summary() 的边界它能给你什么给不了什么summary()是 R 里最省事的入口数值型变量直接吐最小值、下四分位数、中位数、均值、上四分位数、最大值因子和逻辑向量给频数。拿内置的mtcars试一下选mpg、hp、wt三个变量# 加载内置数据集无需额外安装 data(mtcars) # 选定要分析的数值变量 myvars - c(mpg, hp, wt) # 基础描述性统计一行拿到六数概括 summary(mtcars[myvars])这段代码的逻辑很直白mtcars[myvars]按列名取子集summary()对每个数值列分别计算六数概括。参数上没什么可调的它不接受na.rm之类的开关缺失值会以NAs单独计数显示在结果里——这一点很关键看到NAs : 3就说明这一列有 3 个缺失后续算均值标准差时必须显式处理否则结果直接变NA。summary()的短板也很明显不给标准差、不给方差、不给偏度峰度四分位数之外没有更多分位点。它适合做第一眼的体检不适合当最终报告口径。我一般把它当“开机自检”确认列类型对不对、缺失多不多再决定往下用哪套函数。2.2 sapply() 批量套函数把均值、标准差、分位数一次算齐sapply()的价值在于“对每一列应用同一个函数”返回一个命名向量或矩阵天然适合批量出统计量。基础写法是先算均值再算标准差# 对每个变量求均值 sapply(mtcars[myvars], mean) # 对每个变量求标准差 sapply(mtcars[myvars], sd)mean和sd默认都不处理缺失值数据干净时没问题一旦有NA得改成function(x) mean(x, na.rm TRUE)这种匿名函数形式。更实用的做法是一次性把多个统计量拼成一个矩阵方便直接贴进报告# 一次性计算多个统计量结果按变量为行、统计量为列 stats_mat - sapply(mtcars[myvars], function(x) { c( n length(x), # 样本量 mean mean(x), # 均值 sd sd(x), # 标准差 median median(x), # 中位数 min min(x), # 最小值 max max(x), # 最大值 q25 quantile(x, 0.25), # 下四分位数 q75 quantile(x, 0.75) # 上四分位数 ) }) # 转置一下让变量在行、统计量在列读起来更顺 t(stats_mat)这里的关键点是sapply会把匿名函数返回的命名向量按列拼起来所以原始结果是“统计量 × 变量”的矩阵t()转置后才是我们习惯的“变量 × 统计量”。quantile(x, 0.25)的第二个参数就是分位点想要 10%、90% 分位就改成 0.1、0.9比summary()灵活。参数上唯一要盯的是na.rm上面这版没加是因为mtcars本身没有缺失换成真实数据务必在每个函数里补上na.rm TRUE或者先统一清洗。2.3 自定义 mystats偏度和峰度为什么必须自己写summary()和sapply()都覆盖不到偏度skewness和峰度kurtosis而这两个量恰恰是判断分布形状、识别异常值的关键。R 基础包里没有现成函数最稳的办法是自己写一个把样本量、均值、标准差、偏度、峰度打包返回# 自定义描述性统计函数 # na.omit TRUE 时先剔除缺失值再计算 mystats - function(x, na.omit FALSE) { if (na.omit) { x - x[!is.na(x)] } m - mean(x) # 均值 n - length(x) # 样本量 s - sd(x) # 标准差 skew - sum((x - m)^3 / s^3) / n # 偏度 kurt - sum((x - m)^4 / s^4) / n - 3 # 超额峰度 return(c(n n, mean m, stdev s, skew skew, kurtosis kurt)) } # 对三个变量分别应用 sapply(mtcars[myvars], mystats)逻辑说明偏度用三阶中心矩除以标准差三次方峰度用四阶中心矩除以标准差四次方再减 3减 3 是为了让正态分布的峰度归零得到“超额峰度”。参数na.omit默认FALSE意味着有缺失就直接返回NA这是故意的——逼你先确认缺失情况而不是默默丢掉样本。实际用的时候我一般传na.omit TRUE但会在报告里注明剔除了多少条。提示这里的偏度峰度用的是总体公式分母为 n和psych包默认的样本校正公式分母为 n-1 并做偏倚校正算出来会有细微差异。跨工具对比数字前先确认口径一致否则会误以为数据出了问题。3. Hmisc 与 psych 两个 describe装哪个、看哪列、怎么对齐自己写函数灵活但费事日常分析更常见的是直接调包。Hmisc和psych都提供describe()名字一样、输出不一样很多人装完发现两边的偏度对不上就开始怀疑人生。这一章把两者的差异和分组聚合一起讲清楚。3.1 Hmisc::describe()信息最全但输出是文本块Hmisc的describe()输出非常细样本量、缺失数、唯一值数、均值、分位数、极值、偏度峰度都有缺点是返回的是格式化文本想拿数字得手动抠。# 安装并加载 Hmisc install.packages(Hmisc) library(Hmisc) # 对选定变量做详细描述 describe(mtcars[myvars])参数上describe()支持digits控制小数位、omit指定要跳过的变量。它最大的实用点是会列出“最低/最高各 5 个值”排查异常值特别顺手——如果最高 5 个值里出现一个明显离群的数基本就能定位到录入错误。但它不直接返回数据框想批量导出得配合capture.output()或者改用psych。3.2 psych::describe()返回数据框最适合批量出表psych的describe()返回的是一个规整的数据框列包括n、mean、sd、median、min、max、range、skew、kurtosis、se直接能写进 CSV 或者喂给knitr出表。# 安装并加载 psych install.packages(psych) library(psych) # 返回数据框便于后续导出 desc_df - describe(mtcars[myvars]) desc_df参数上常用的是fast TRUE跳过一些耗时计算大数据集下明显更快quant可以指定额外要算的分位点比如quant c(.1, .9)。注意psych的skew和kurtosis默认带样本校正和 2.3 节手写公式的结果不完全相等这是正常的不是谁算错了。选型上我的习惯是要快速看分布细节用Hmisc要批量出表、接下游流程用psych。3.3 分组聚合三件套aggregate、by、summaryBy 怎么选真实数据几乎都要分组看比如按某个分类变量拆开算均值。R 里有三条路适用场景不同。aggregate()最简洁公式接口适合只算一两个统计量# 按 cyl 分组计算 mpg 的均值 aggregate(mpg ~ cyl, data mtcars, mean)by()适合对每组应用一个返回多值的函数比如把 2.3 节的mystats套进去# 先定义一个对数据框每列应用 mystats 的包装 dstats - function(x) sapply(x, mystats) # 按 cyl 分组对 mpg/hp/wt 三列分别算全套统计量 by(mtcars[myvars], mtcars$cyl, dstats)by()的返回是一个列表每组一个元素打印出来层级较深适合交互式查看不适合直接导出。doBy包的summaryBy()则是“分组 多统计量 返回数据框”一步到位最适合出报告# 安装并加载 doBy install.packages(doBy) library(doBy) # 按 cyl 分组对三个变量应用 mystats结果直接是数据框 summaryBy(mpg hp wt ~ cyl, data mtcars, FUN mystats)三者的取舍只要一个均值用aggregate要套自定义多值函数、临时看看用by要批量出结构化结果、接可视化或导出用summaryBy。参数上summaryBy的FUN接受任何返回向量的函数mystats返回命名向量所以结果列名会自动带上n、mean、skew这些名字省去手动改列名。4. ggplot2 出图直方图与箱线图里藏着的分布真相数值表再全也不如一张图直观。ggplot2的直方图和箱线图是描述性统计的标配但默认参数经常把真相藏起来——分箱太粗看不出双峰箱线图把离群点画成一堆点却不说有多少个。4.1 直方图binwidth 选错双峰变单峰# 安装并加载 ggplot2 install.packages(ggplot2) library(ggplot2) # mpg 的直方图binwidth 控制分箱宽度 ggplot(mtcars, aes(x mpg)) geom_histogram(binwidth 1, fill blue, color black)binwidth 1表示每个柱子覆盖 1 个单位的区间。这个参数是直方图最容易翻车的地方设太大双峰分布会被抹成单峰设太小柱子碎成锯齿看不出趋势。实操里我一般先用binwidth diff(range(x))/30估一个初值再手动微调。fill和color分别控制填充色和边框色纯审美参数不影响统计结果。4.2 箱线图分组看离散度和离群点# 按 cyl 分组看 mpg 的箱线图 ggplot(mtcars, aes(x factor(cyl), y mpg)) geom_boxplot()x factor(cyl)这一步不能省cyl是数值型不转因子的话 ggplot 会把它当连续轴箱线图就画不出来。箱线图能同时给出中位数、四分位距和离群点配合第 3 章的分组统计量一起看能快速判断“某组均值高是因为整体偏高还是因为几个极端值拉上去的”。如果离群点特别多可以加outlier.shape NA先隐藏再单独用散点图层标出来避免图面糊成一团。注意箱线图的“离群点”判定是 1.5 倍四分位距这是统计惯例不是错误。看到一堆点别急着删先回到Hmisc::describe()看极值列表确认是录入错误还是真实的长尾。5. 避坑与排查五个让描述性统计结果失真的常见问题这一章是我自己踩过、也见过别人反复踩的坑每条按“现象 → 原因 → 解决”写照着排查能省不少返工。现象一均值算出来是NA但数据看着挺完整。原因某一列存在缺失值mean()默认na.rm FALSE一个NA就让整个结果变NA。解决先colSums(is.na(df))数一遍缺失再决定是na.rm TRUE还是先插补千万别在没确认缺失比例的情况下直接na.omit样本量悄悄少一半是常事。现象二psych::describe()和手写mystats()的峰度差了好几个点。原因两者公式不同psych默认做样本偏倚校正手写版是总体公式。解决统一口径要么全用包函数要么全用手写报告里注明用的是哪一种跨工具对比前先拿一组标准正态随机数验证。现象三aggregate()分组后某些组直接消失。原因分组变量里有NAaggregate()默认把NA组丢掉且不报错。解决分组前table(df$group, useNA ifany)看一眼有没有NA组有的话决定是归入“未知”类还是剔除别让它无声消失。现象四直方图看着是单峰但偏度算出来明显不为零。原因binwidth太大把双峰或长尾抹平了。解决把binwidth调小到原来的三分之一再画一次同时对照describe()的偏度值和极值列表交叉验证。现象五summaryBy()报错说FUN返回长度不一致。原因传进去的函数在不同组返回的向量长度不同比如某组全是NA导致sd()返回NA而其他统计量正常。解决在自定义函数里对NA做显式处理保证任何输入都返回固定长度的命名向量这是批量聚合能跑通的前提。6. 把口径固化成模板一个可复用的描述性统计函数与验证习惯前面几章的函数都是散的真正干活时我习惯把它们收拢成一个入口函数输入数据框和变量名一次吐出数值表加两张图避免每次重新拼代码。核心思路是把 2.3 节的mystats、3.2 节的psych::describe()和 4 章的绘图串起来# 一站式描述性统计返回统计表并可选输出图 desc_report - function(df, vars, group NULL, plot TRUE) { sub - df[vars] # 数值统计表psych 返回数据框便于导出 stat_tbl - psych::describe(sub, fast TRUE) # 分组统计若指定分组变量 if (!is.null(group)) { grp_tbl - doBy::summaryBy( reformulate(vars, response group), data df, FUN mystats ) print(grp_tbl) } # 可选每个变量画一张直方图 if (plot) { for (v in vars) { p - ggplot2::ggplot(df, ggplot2::aes(x .data[[v]])) ggplot2::geom_histogram(binwidth diff(range(df[[v]], na.rm TRUE)) / 30, fill steelblue, color black) ggplot2::labs(title paste(Distribution of, v)) print(p) } } return(stat_tbl) } # 调用示例 desc_report(mtcars, c(mpg, hp, wt), group cyl)这段代码里几个参数值得说清楚reformulate(vars, response group)动态拼出mpg hp wt ~ cyl这种公式变量名多的时候不用手写.data[[v]]是 ggplot2 的 tidy 评估写法循环里传字符串变量名必须这么写直接写aes(x v)会把v当成列名去找然后报错binwidth用diff(range(...))/30自动估初值比写死数字稳。fast TRUE在变量多、样本大时能明显提速。验证习惯上我每次跑完这套都会做三件事一是拿summary()的结果和psych的median对一遍中位数对不上说明子集取错了二是看n列是否等于预期样本量少了就是缺失值在作祟三是随机抽一个变量手算一遍均值和标准差和函数结果比对。这套“三查”花不了两分钟但拦下过好几次因为列名拼错、子集取错导致的整表失真。从那以后我每次接手新数据集都强制先跑一遍desc_report再动任何模型宁可前面多花十分钟也不想在建模阶段回头查“这个均值怎么这么怪”。希望这套模板能帮到你少走几段我走过的弯路。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/29 4:38:59

Superpowers安装指南:浏览器里的轻量级游戏开发IDE

最近后台好几个朋友在搜“superpowers”这个词,我一看搜索记录里还带着“想要安装superpowers”这种需求,第一反应是:大家是不是把它当成什么系统增强工具、电源管理插件了?单看这个英文单词,直译就是“超能力”&#…

2026/10/29 4:38:59

ponytail:AIGC时代微型物理系统的校验标尺

1. 项目概述:从“ponytail”这个词看当代视觉表达的底层逻辑“ponytail”这个词最近在多个内容平台高频出现,但它既不是新发布的软件、也不是某款硬件设备的代号,更不是某个技术协议的缩写。它是一个具象到近乎本能的身体语言符号——马尾辫。…

2026/10/29 4:38:59

ponytail:一种高效专注的行为启动符号

1. 项目概述:从“ponytail”这个词出发,我们到底在聊什么?“ponytail”这个词最近频繁出现在社交平台的搜索热榜和内容推荐流里,但它既不是新发布的App,也不是某款硬件产品的代号,更不是某个技术协议的缩写…

2026/10/29 5:59:02

ChatGLM私有化智能问答助理本地部署:环境版本配对与避坑指南

简介:面向希望将智能问答系统私有化落地的开发者与课程学习者,这套示例项目以 Gradio 搭建交互界面,结合 FAISS 向量检索与 Sentence-Transformers 文本嵌入,演示文件上传、知识库构建与对话问答的完整链路,帮助理解本…

2026/10/29 5:59:02

从原理到实操,马尾辫发型全解析:扎出好看又舒服的秘诀

说实话,马尾辫可能是我人生中第一个会的发型,也是到现在为止唯一一个十年都没腻的发型。十几年前刚开始折腾头发那会儿,每天出门前就一个动作——把所有头发往后一拢,皮筋一套,完事。那时候我以为马尾辫就只是"把…

2026/10/29 5:59:02

无线信道扫描优化:从原理到实战的6种加速方案

1. 无线信道扫描的痛点与优化需求在无线网络优化工作中,全信道扫描是个绕不开的基础操作。以常见的双频路由器为例,2.4G频段有13个信道(实际可用11个),5G频段在国内有27个信道(36-64、149-165等&#xff09…

2026/10/29 5:59:02

MySQL数据类型长度解析:INT与VARCHAR的本质区别

1. 数据类型长度问题的本质在MySQL中,当我们在设计表结构时,经常会遇到需要为字段指定"长度"的情况。比如INT(10)、VARCHAR(255)这样的定义。但很多开发者其实并不真正理解这两个"长度"概念的本质区别,这往往会导致一些设…

2026/10/29 5:59:02

本地语音转写全流程实战:从口音适配到说话人分离与模型微调

写完上一轮从零实现的本地测绘工具后,顺手把整套思路复用到另一个折腾了两个月的小项目上,现在总算能坐下来把过程整理成文。这个工具我叫它caveman,本质上是一个面向“自己人”的轻量级语音转写服务,重点解决两件事:一…

2026/10/29 5:54:02

Tomcat JNI版本不兼容问题分析与解决方案

1. 问题现象与背景分析最近在启动一个基于Tomcat 8.5.41的Java Web项目时,控制台突然抛出"unsupported JNI version 0xFFFFFFFF required by D:\apache-tomcat-8.5.41\bin\tcnative-1.dll"的错误。这个报错直接导致Tomcat无法正常启动,项目自然…

2026/10/28 14:42:12

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/28 15:28:56

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/28 3:32:29

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/29 0:03:42

学生选课系统DFD图绘制指南:边界划分与分层校验实战

简介:文档以顶层与第一层DFD图为核心,完整刻画学生选课系统的逻辑模型,面向软件工程课程设计、系统分析学习及毕设前期建模人群。顶层图界定系统边界,外部实体包括管理员、教师和学生三类角色;第一层图进一步细化用户登…

2026/10/29 0:03:42

JIRA敏捷落地:Scrum角色权限、Sprint与燃尽图避坑指南

简介:围绕“基于JIRA的敏捷开发项目管理”这一主题,面向产品负责人、Scrum Master及研发测试成员,梳理Scrum角色分工、迭代流程与JIRA工具配置的对应关系,适合初、中级团队导入敏捷管理时参考。压缩包共1个docx文件,大…

2026/10/29 0:03:42

SEMI S8人机工程验收实战:从条款拆解到现场实测的完整指南

简介:面向半导体设备设计、制造与运维工程师及安全合规人员,这份资料聚焦SEMI标准体系下的设备安全规范,重点收录SEMI S8-0308《半导体制造设备人体工程学工程安全指南》。内容围绕设备设计原则、错误与事故预防、人体工程学适配三大主线展开…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑