☰
R语言常用函数汇总:数据清洗、分组统计与统计检验实战指南
2026/10/21 19:41:29 网站建设 项目流程

简介:这是一份面向R语言学习者的常用函数速查PDF,内容按数学、统计、概率、字符处理和实用工具五类整理,覆盖abs()、sqrt()、round()等基础数学运算,mean()、sd()、quantile()、scale()等统计描述函数,以及二项分布、正态分布、泊松分布等常见概率分布的d/p/q/r系列用法。文档同时收录substr()、grep()、strsplit()、paste()等字符处理函数,和seq()、rep()、cut()、cbind()、rbind()等数据操作工具,每个函数均配有简洁的语法说明与典型示例,便于对照学习。压缩包内为单个PDF文件,大小仅50KB,内容精炼、随查随用,适合数据分析初学者、科研人员及备考学生作为日常参考手册。目前已有294人浏览学习,这份汇总能帮助读者快速定位所需函数,减少翻阅文档的时间,有效提升R语言编程效率。

1. 为什么你需要一份R语言常用函数汇总

拿到《学习R语言常用函数汇总》这份PDF,大多数人第一反应是当字典用,遇到问题翻一翻,结果翻到第十页就搁下了。真正的麻烦在于:R的常用函数散落在base、stats、utils这些基础包和dplyr等第三方包里,数量看着吓人,但日常高频使用的不过七八十个;要是按字母顺序去背,学一个月也记不住几个。这份汇总真正值钱的地方,是帮你建立一套分类逻辑——数据读入、结构转换、清洗筛选、分组计算、统计检验与随机模拟,函数名有了挂靠点,才不会学了就忘。

这篇文章就按这条主线展开,每个函数都给最小可运行的示例、参数说明和容易踩的坑。适合刚入门R、准备用R做数据分析的人,也适合从Excel或SPSS转过来、一时适应不了函数式操作的从业者。新手照章节顺序跑一遍,熟手可以直接跳到第5章的避坑清单。

很多人卡在第一步,不是看不懂函数,而是不知道“现在该用哪个函数”。所以下面每一章都会先讲清楚这类任务里函数是怎么分工的,再给代码和参数,最后才说坑。

2. 把数据装进R:read.csv、data.frame与类型转换实战

2.1 读入与写出:read.csv 家族的参数决定数据质量

在R里见到数据的第一步永远是读文件。read.csv是逗号分隔文件的标配读法,但它远没有看起来那么简单。很多人第一次读带中文的CSV,读出来全是乱码,或者发现原本是字符型的列变成了因子,根源都在参数上。我一般会这样写:

# 最常用的读入方式 mydata <- read.csv("data/sales.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8", na.strings = c("", "NA", "NULL")) # 写出数据,row.names = FALSE 避免多出一列行号 write.csv(mydata, "output/sales_clean.csv", row.names = FALSE, fileEncoding = "UTF-8") # 保存与恢复 R 对象,适合保留中间处理结果 saveRDS(mydata, "output/sales.rds") mydata2 <- readRDS("output/sales.rds")

代码逻辑很直接:read.csv返回的是data.frame,后续所有操作都基于这个对象。saveRDS和write.csv的区别值得说一句:write.csv是给人看的,导出后能用Excel打开;saveRDS是给R自己看的,能完整保留因子水平、日期类型这些属性,不会在往返转换中丢信息。中间步骤我倾向于用saveRDS,最后交付才用write.csv。

这里有几个参数是高频踩坑点:

参数作用建议值
stringsAsFactors是否把字符列转成因子FALSE,避免隐式转换
fileEncoding文件编码中文数据一般用UTF-8
na.strings哪些字符串视为缺失值按数据实际填充值设置
row.names写出时是否带行号FALSE,避免污染数据

fileEncoding这个参数最容易被忽略。很多从Excel另存出来的CSV是GBK编码,直接用默认参数读会乱码;反过来,UTF-8文件用GBK解析也一样乱。先确认数据来源的编码,再决定参数,比事后清洗乱码省事得多。

提示:文件编码问题在Windows上尤其常见。读入后先跑一遍head()看中文列是否正常,再往下做,别等到画图时才发现标签全是乱码。

2.2 数据结构与类型转换:c、list、data.frame 与 as.* 家族

R里“一切皆向量”这句话听着玄,其实是理解函数的钥匙。c()造向量,list装不同类型的东西,data.frame是表格,这三个结构覆盖了绝大多数日常操作。刚接触的人最容易犯的错是把data.frame当矩阵用,或者忘了向量只能装一种类型。

# 三种基础结构 vec <- c(1, 5, 3, 8) # 数值向量 lst <- list(name = "A同学", score = 88, tags = c("r", "data")) # 异构列表 df <- data.frame(id = 1:3, name = c("x", "y", "z"), stringsAsFactors = FALSE) # 数据框 # 读入数据后第一步:体检 class(df) str(df) dim(df) # 类型转换 num <- c("12.5", "3.8", "9.1") num2 <- as.numeric(num) # 字符转数值 bad <- as.numeric(c("12", "abc")) # 转不了的元素变成 NA # 数据框增列与拼接 df$score <- c(90, 85, 92) df2 <- rbind(df, df) # 行拼接 df3 <- cbind(df, id2 = 1:3) # 列拼接

逻辑说明:str是体检第一函数,它把每个列的类型和长度打印出来,一眼就能看出哪个列被读成了因子、哪个列是字符型数值。class看对象的“大类型”,typeof看底层存储类型,多数场景看class就够。as.numeric转换失败时返回NA并给警告,这个行为是好事——它提醒你数据里有非数值内容,而不是默默算出一个错误结果。

一个常见误用是拿data.frame的列做运算时不加$或[[]],或者把向量拼进data.frame时长度不一致报错。记住data.frame要求每一列等长,这是它的硬约束。list没有这个约束,所以需要“一列里装不同长度的东西”时用list,常规表格用data.frame。

2.3 快速体检:head、dim、summary、unique 的连招

读入数据之后不要急着建模,先做一轮体检。我这套组合拳常年用:

head(df) # 前 6 行,看数据长什么样 dim(df) # 维度:多少行多少列 nrow(df) # 单独取行数 ncol(df) # 单独取列数 summary(df) # 每列的描述统计 unique(df$name) # 某个列的不重复值 table(df$name) # 频数表

这套组合动作解决三个问题:数据是否完整、每列类型是否符合预期、分类列里到底有哪些取值。table配合unique看因子列的分布特别有效,比如group列里有"A""B"之外混了个"a",一眼就能发现大小写不一致的问题。head默认显示6行,想看更多就head(df, 20),tail是看尾部。

体检的目的不是走过场,而是给后面每一步操作定基线。比如summary里发现某列有NA,后面分组计算之前就要决定是删是补;unique发现取值比预想多,就要检查是不是数据录入有误。这个习惯能帮你省掉后面80%的返工。

3. 数据清洗与分组计算:筛选、排序、分组统计一次讲清

3.1 筛选、排序与去重:subset 与 order 组合

清洗数据的核心动作就三个:按条件筛行、按某列排序、去掉重复记录。R提供了两条路,一条是subset这种“说人话”的写法,一条是用中括号加逻辑索引的程序式写法。初学先用subset,写惯了再用后者,因为后者是理解apply家族和更复杂索引操作的基础。

# 筛选:score 大于等于 80 且 group 为 A sub1 <- subset(mydata, score >= 80 & group == "A") # 等价的中括号写法,注意逗号的位置 sub2 <- mydata[mydata$score >= 80, ] # 排序:order 返回的是行号顺序,不是排序后的数据 mydata[order(mydata$score, decreasing = TRUE), ] # 单列降序 mydata[order(mydata$group, mydata$score), ] # 先 group 再 score # 去重 mydata[!duplicated(mydata$id), ] # 按 id 去重,保留第一次出现的行 unique(mydata$group) # 直接取不重复的值

参数说明:order返回的是索引向量,这是新手最容易绕晕的地方——order(x)本身不是排序结果,必须放进中括号里写成mydata[order(x), ]才是排序后的数据框。decreasing控制升降序,多列排序时后面的列是次要排序键。duplicated返回逻辑向量,TRUE表示该行是重复项,取反!duplicated(...)就是“保留第一次出现”,这个模式在去重场景里几乎是标准答案。

筛选和排序有一个隐蔽的坑:用中括号写条件时,条件里有NA的行会直接被丢掉,因为NA >= 80的结果是NA,而NA在逻辑索引里被视为FALSE。所以筛选前要想清楚,NA是应该保留还是剔除,不要默认系统替你做了决定。如果确实要保留NA行,得显式写成is.na(mydata$score) | mydata$score >= 80。

3.2 分组统计三剑客:tapply、aggregate、by

分组计算是数据分析的高频动作。R基础包里给了三个长得像、用法却有差异的函数:tapply、aggregate、by。我一般按这个标准选:只要结果还要继续做数据处理,就用aggregate,因为它返回data.frame;只是看一眼结果,用tapply最省事;要输出多个统计量,用by。

# tapply:一列数值按一个分组因子算统计量 tapply(mydata$score, mydata$group, mean, na.rm = TRUE) # aggregate:公式写法,支持多分组列,返回 data.frame aggregate(score ~ group + gender, data = mydata, FUN = mean, na.rm = TRUE) # by:返回 list,适合对子集做复杂操作 by(mydata[, c("score", "age")], mydata$group, summary)

三者的差别可以这样记:tapply返回的是带名字的数组,索引是分组值;aggregate把分组列变成普通列,结果可以直接喂给write.csv或后续merge;by返回list,每个组的子集都会被函数完整处理一遍,适合做“每个组单独跑一次模型”这类任务。公式写法score ~ group是R的统计传统,读作“score按group分组”,记住这个语法,后面t.test、lm全是同一套。

FUN参数是分组计算的核心:可以传mean、median、sum、sd,也可以传自定义函数。注意na.rm不是tapply的参数,而是传给mean的参数;如果你写的函数没有na.rm参数,传进去会直接报unused argument错误。我踩过这个坑,详见第5.2节。

3.3 想少敲代码:dplyr 五动词是当前主流写法

基础包的分组函数概念清楚,但写多步清洗时嵌套严重。当前项目的常见做法是引入dplyr,用五个动词加管道符号一条龙写完。dplyr不是基础包的替代,而是覆盖了筛选、选列、改列、分组、汇总五类高频操作,mutate比逐列赋值更接近“数据处理流水线”的思路。

library(dplyr) clean_df <- mydata %>% filter(score >= 80) %>% # 筛行 select(id, group, score) %>% # 选列 mutate(score_z = (score - mean(score, na.rm = TRUE)) / sd(score, na.rm = TRUE)) %>% # 新增标准化列 group_by(group) %>% # 分组 summarise(avg_score = mean(score, na.rm = TRUE), n = n()) # 汇总

管道符号%>%的意思是把左边的结果作为第一个参数传给右边的函数,整段代码从“读数据”到“出汇总”是一条直线,不用一层层包括号。filter对应基础包的subset,select对应取列,mutate对应新增列,group_by加summarise对应aggregate。五动词的记忆方式:筛选、选列、改列、分组、汇总,正好覆盖清洗流程的每一步。

注意一个细节:dplyr加载后会自动屏蔽stats包里的filter函数,这就是第5.5节要说的函数名冲突。如果汇总文档里同时教了基础包和dplyr,请务必记住“函数归属”这件事,否则同样的代码在不同环境里可能跑出不同结果。

4. 统计检验与随机模拟:分布函数d/p/q/r规律一把梭

4.1 描述统计一套带走:summary、quantile、cor

R的统计函数不是单个函数,而是可以组合的积木。描述统计最省事的起点是summary,它一次性给出最小值、四分位数、均值、中位数和最大值;但要算标准差、协方差,summary就不够了,得上sd和cor。

summary(mydata$score) # 五数概括 + 均值 quantile(mydata$score, probs = c(0, 0.25, 0.5, 0.75, 1), na.rm = TRUE) # 自定义分位点 mean(mydata$score, na.rm = TRUE) # 均值 sd(mydata$score, na.rm = TRUE) # 标准差 # 相关系数矩阵:use 参数决定 NA 处理方式 cor(mydata[, c("score", "age", "hours")], use = "complete.obs")

参数说明:mean、sd、quantile这些函数都接受na.rm参数,默认为FALSE,这是R与Excel的一个重大区别——Excel的AVERAGE会忽略空白单元格,R的mean遇到NA会直接返回NA。use = "complete.obs"是cor处理缺失值的常用选项,表示只用所有变量都完整的行计算,避免pairwise方式带来的“不同对用不同样本量”问题。

新手容易犯的错是把summary用在非数值列上。summary对因子列输出的是频数,对字符列输出的是长度和类别数,这其实是特性而不是bug——一份summary输出里同时看到数值列的五数概括和因子列的频数,反而能快速定位“哪列类型不对”。

4.2 分布函数四件套:d/p/q/r 前缀规律

R的随机数函数有一套统一的命名规律:每个分布都有四个函数,前缀分别是d、p、q、r,对应密度、累积概率、分位数、随机数。以正态分布为例,rnorm生成随机数,dnorm算密度,pnorm算累积概率,qnorm算分位数。记住这套规律,遇到t分布、F分布、卡方分布、二项分布全都能类推。

set.seed(42) # 固定随机种子,结果可复现 x <- rnorm(100, mean = 70, sd = 10) # 生成 100 个 N(70, 10) 随机数 density_at_mean <- dnorm(70, mean = 70, sd = 10) # x=70 处的概率密度 prob_less_80 <- pnorm(80, mean = 70, sd = 10) # P(X <= 80) q_975 <- qnorm(0.975, mean = 70, sd = 10) # 97.5% 分位数 # 随机抽样的常用函数 sample(1:100, size = 10, replace = FALSE) # 不放回抽样 runif(5, min = 0, max = 1) # 均匀分布随机数

参数说明:set.seed是模拟实验里最容易被忽略却又最重要的一行。没有它,每次运行rnorm都会得到不同的随机数,结果无法复现;有了它,只要种子相同,随机数序列就完全一致。pnorm的返回值是累积概率,这在假设检验里就是p值的基础;qnorm是它的逆运算,算置信区间临界值必备。sample的replace参数决定是否放回,不放回时size不能超过总体长度。

这四个前缀的规律性极强,建议直接写进自己的速查卡。rbinom对应二项分布抽样,dpois对应泊松密度,pexp对应指数分布累积概率,全部沿用同一套命名,学一个等于学五个。汇总PDF里凡是出现分布函数,都可以按这个规律自查参数顺序。

4.3 一个检验走完假设检验流程:t.test 与 chisq.test

假设检验是统计分析的基本动作,R里一行就能跑完。最常用的是t.test,用来比较两组均值是否有显著差异;chisq.test用来检验两个分类变量是否独立。两者都支持公式写法,这在前面aggregate里已经见过。

# 两组均值比较,公式写法等同于按 group 分组 t.test(score ~ group, data = mydata) # 默认做 Welch 修正,不假设两组方差相等 t.test(score ~ group, data = mydata, var.equal = TRUE) # 分类变量独立性检验 chisq.test(table(mydata$group, mydata$pass)) # 非参数版本:数据不服从正态时用 wilcox.test(score ~ group, data = mydata)

t.test的输出里需要重点看三样东西:p值、置信区间、估计的均值差。p值小于0.05只能说“差异在统计意义上显著”,不能说“差异很大”,这是常被误读的一点。var.equal默认是FALSE,也就是Welch修正版,这在两组方差不等时更稳健;反过来,如果你明确知道方差齐性成立,设TRUE能提高检验功效。

chisq.test注意期望频数不能太小,一般要求所有期望频数大于5,否则检验结果不可信,这时考虑改用Fisher精确检验。跑完检验别只盯着p值,先去看table()输出的实际频数分布,很多“显著”其实来自个别格子的极端值。

4.4 画图三件套:plot、hist、boxplot 快速出图

统计结果配一张图才完整。R基础绘图里最常用的三个函数是plot画散点、hist画直方图、boxplot画箱线图。它们的共同点是“给什么数据就出什么图”,不需要额外加载包,适合快速探索。

plot(mydata$hours, mydata$score) # 散点图:看两变量关系 hist(mydata$score, breaks = 20) # 直方图:看分布形态 boxplot(score ~ group, data = mydata) # 箱线图:分组比较

breaks控制直方图的分组数量,数值越大柱子越密,画出来越接近密度曲线。boxplot的公式写法score ~ group和t.test完全一致,一张图就能看出各组的中位数、四分位数和离群点。画图之前先跑summary检查数据范围,避免个别异常值把坐标轴拉得没法看。

5. R函数学习避坑指南:5个高频翻车现场与排查方法

5.1 现象:字符列读进来就变成因子,排序筛选全乱

读入CSV后发现原本是姓名的列变成了整数编码,或者str显示factor类型,排序时按字母序而不是你想要的顺序,这是base R老版本最经典的暗坑。原因在于read.csv默认stringsAsFactors = TRUE,把纯字符列自动转成因子,因子底层是整数,表现起来就是“看着是字符串,算起来是数字”。

解决方法是读入时显式设置stringsAsFactors = FALSE,或者在创建data.frame时同样设置。已经读进来的数据补救也不难:as.character()把因子转回字符。要注意的是因子转字符时取的是水平值而不是原始字符串,如果存在未出现的水平,转换后可能留下“幽灵水平”,用droplevels()清理。

5.2 现象:明明有数据,mean() 却返回 NA

算均值、求和时结果莫名其妙是NA,这是新手最常遇到的“结果消失”事件。原因很简单:列里包含缺失值NA,而mean、sum、sd这些函数的na.rm参数默认是FALSE,遇到NA就整个返回NA。这不是bug,是R的保守设计——它宁可给你一个明确的缺失结果,也不给一个可疑的数字。

解决方式有两个层次。一层是临时处理:在调用时传na.rm = TRUE。另一层是全局处理:先用na.omit()删掉含NA的行,或用is.na()定位缺失值、单独决定怎么补。我一般建议先is.na()查看缺失分布,再决定是删是补,直接na.rm会把“存在缺失”这件事掩盖掉。

5.3 现象:for 循环跑大表,等到怀疑人生

用for循环一列一列地处理几万行的数据框,速度慢到像卡死。原因是R是向量化语言,同样一个操作作用于整个向量时走的是底层编译好的C代码,逐元素循环则反复在R解释器里调度,开销差着数量级。

解决方法是优先用向量化写法:能整列算就整列算,比如ifelse代替逐行if,rowSums代替按行求和。需要按组或按行做复杂操作时,用apply家族。但反过来说,几万行以下的for循环其实毫无问题,为了“显得专业”硬改成apply反而降低可读性,这个平衡要自己把握。

5.4 现象:read.csv 报 cannot open file,路径明明没问题

读文件时报cannot open file,第一反应是文件名拼错了,其实八成是工作目录不对。R的相对路径是相对于当前工作目录的,而RStudio默认的工作目录可能是你的用户主目录,根本不是项目文件夹。

排查顺序:先getwd()看当前目录,再file.exists("data/sales.csv")确认文件是否在预期位置,最后setwd()切换或用绝对路径。更省心的做法是在RStudio里为每个项目建一个.Rproj,工作目录自动绑定项目根目录,告别setwd玄学。

5.5 现象:加载 dplyr 后 filter() 行为突变

原本用得好好的filter()突然报错,或者同样的代码前一天还正常、后一天结果不同。原因大概率是函数名冲突:dplyr和stats包都有filter函数,后加载的包会屏蔽先加载的。类似的冲突还有lag、intersect等。

解决方法是显式指定归属:dplyr::filter()直接用双冒号调用,既避免冲突又让读代码的人知道函数来自哪个包。也可以用conflict检测工具查看当前哪些函数被屏蔽。这是写R长期项目必须养成的习惯,汇总PDF里凡是列了dplyr函数的,都应该配套标注包名。

6. 把函数地图装进脑子:args、example与apply批处理技巧

6.1 遇事不决先查函数三件套:args、example、help

汇总PDF只能覆盖常用函数,真到项目里遇到陌生函数,最可靠的不是搜索引擎,而是R自带的帮助系统。args()看参数列表,example()直接运行官方示例,help()看完整文档。这三个函数配合使用,十分钟内就能搞懂一个新函数能不能用、怎么用。

args(mean) # 查看参数名和默认值 example(mean) # 运行官方示例,直观看到结果 help("mean") # 打开完整文档 ?mean # help 的简写

6.2 按数据任务整理自己的速查卡

汇总PDF是按函数类别组织的,但实际工作是按任务组织的。我建议按“读数据、清洗、分组统计、检验、画图”五个任务维度重排一份自己的速查卡,每个任务下只放5到10个函数。每周从PDF里挑10个函数抄进卡片,抄的过程比看的过程记忆深得多。

6.3 用 apply 家族体会函数式写法

最后一个技巧是主动用apply家族练批量操作,这是从“会单个函数”走向“会组织代码”的关键一步。比如按组批量跑线性回归:

# 按组批量跑线性回归 models <- by(mydata, mydata$group, function(d) { lm(score ~ hours, data = d) }) # 提取每个模型的系数 coef_list <- lapply(models, coef) sapply(coef_list, function(x) x["hours"])

by的返回值是list,每个元素是一个组的模型对象;lapply对list里的每个模型提取系数,sapply再把结果简化成向量。这一串组合看起来绕,但本质就是“对每个组做同样的事”,和tapply的分组思路一脉相承。

我自己的习惯是,每学一个函数就往一个run_examples.R脚本里追加最小示例,升级R版本后跑一遍,比翻PDF快得多。汇总文档给你的是地图,真正认路还得靠手敲。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询