1. 项目概述:为什么从这50个函数开始?
如果你刚打开RStudio,面对一个空白的脚本窗口,感觉有点无从下手,那你来对地方了。我刚开始学R的时候,也经历过这个阶段:网上教程一搜一大堆,各种包和函数看得人眼花缭乱,但真到自己动手处理数据时,却连怎么把数据读进来、怎么看一眼数据长什么样都搞不清楚。后来我发现,与其贪多嚼不烂,不如先把最基础、最高频的那一批函数吃透。这就像学武功先扎马步,学编程先掌握这些“生存必备”函数。今天要聊的这50个函数,就是我结合自己多年数据分析的经验,从R语言海量函数库里精挑细选出来的“核心生存包”。它们覆盖了数据导入、清洗、转换、探索、分析和可视化的全流程,掌握了它们,你就能独立完成80%以上的基础数据分析任务。无论你是学生、研究员,还是刚转行的数据分析师,这篇文章都能帮你绕过我当年踩过的坑,快速建立起对R语言的实用手感。
2. 核心思路:如何构建你的R函数知识地图
学习函数最怕死记硬背。我的方法是按工作流和功能域来分类记忆,把零散的函数点串联成解决问题的线。这50个函数,我大致把它们归为六个核心模块,这基本对应了一次数据分析的完整路径:
- 数据基石模块:解决“数据从哪来”和“数据长啥样”的问题。包括读取数据、查看数据结构和基本信息。
- 数据整形模块:解决“数据太乱”的问题。专注于子集选取、行列操作、排序和去重。
- 数据转换与计算模块:解决“数据怎么算”的问题。涵盖数学统计运算、分组汇总以及创建新变量。
- 逻辑控制与迭代模块:解决“自动化处理”的问题。掌握条件判断和循环,让代码能应对复杂情况。
- 可视化入门模块:解决“数据如何呈现”的问题。用最基础的绘图函数把数据变成直观的图表。
- 实用工具模块:解决“效率与调试”问题。包括常用函数、帮助系统和环境管理。
这个分类的好处是,当你面对一个具体任务时,能立刻想到该去哪个“工具箱”里找工具。比如要清洗数据,你就去“数据整形模块”;要算平均值,就去“转换与计算模块”。接下来,我们就按这个地图,一个模块一个模块地拆解。
3. 数据基石模块:读得进来,看得明白
任何分析的第一步都是把数据弄到R的环境里。这个模块的函数是你的起手式。
3.1 数据读取函数:打开数据世界的大门
read.table()和read.csv()是你最常打交道的两个函数,用于读取文本格式的数据。虽然read.csv本质上是read.table的一个预设了逗号分隔符等参数的版本,但细节决定成败。
# 使用 read.csv 读取最常见的逗号分隔文件 my_data <- read.csv("data.csv") # 使用 read.table 应对更复杂的场景 my_data2 <- read.table("data.txt", header = TRUE, sep = "\t", na.strings = "NA")注意:
read.csv默认假设文件有表头(header = TRUE)、用逗号分隔(sep = “,”)。如果你的数据是制表符分隔的.txt文件,用read.csv就会读成一整列。这时应该用read.table(file, sep = “\t”)或者直接用read.delim()。另一个关键参数是na.strings,它告诉R哪些值应该被识别为缺失值(NA),比如空单元格、“NULL”、“NA”等,统一处理缺失值对后续分析至关重要。
对于Excel文件,我强烈建议不要直接在R里读.xlsx。更好的工作流是:1)在Excel中将其另存为.csv格式;2)用read.csv()读取。这样可以避免很多编码和依赖包的问题。如果非要直接读,readxl包里的read_excel()函数是更现代、更可靠的选择。
3.2 数据探查函数:第一眼诊断
数据读进来后,别急着分析,先花几分钟“望闻问切”。
str():这是我的最爱,“结构”函数。它一口气告诉你对象的类型、维度、以及每一列的数据类型和前几个值。str(my_data) # 输出会显示:这是 data.frame,有100个观测(行)、5个变量(列) # 然后列出每一列,如 $ Name: chr [1:100] “Alice” “Bob” ... # 一眼就能看出‘Age’列是不是不小心被读成了字符型(chr)。head()和tail():分别查看数据框的前6行和后6行。快速确认数据读取是否正确,格式是否正常。names()或colnames():获取或设置数据框的列名。清洗数据时经常需要重命名不友好的列名。names(my_data)[1] <- “ID” # 将第一列列名改为“ID”dim():获取对象的维度,返回(行数,列数)。nrow()和ncol()则分别获取行数和列数。summary():对数据框进行描述性统计。对于数值型变量,给出最小值、四分位数、均值、最大值;对于因子型变量,给出频数。快速发现异常值(比如年龄出现负数或极大值)。
实操心得:养成
str()和summary()的肌肉记忆。我每次读入新数据,都会先运行这两个命令。str()能立刻发现数据类型错误(比如数字被读成字符串),而summary()能快速发现异常值和缺失值数量,这能节省后面大量的调试时间。
4. 数据整形模块:把数据收拾服帖
原始数据很少是完美的,这个模块的函数帮你切片、筛选、排序,把数据整理成分析需要的形状。
4.1 子集选取函数:精准定位你需要的数据
选取数据的核心是[(方括号) 操作符,但理解其逻辑是关键。
按位置选取:
df[row_indices, col_indices]my_data[1:5, ] # 选取第1到5行,所有列 my_data[, c(“Name”, “Age”)] # 选取所有行,“Name”和“Age”列 my_data[3, 2] # 选取第3行第2列那个具体的值按条件选取:这是更强大的方式。在方括号内使用逻辑判断。
# 选取年龄大于30的所有行 my_data[my_data$Age > 30, ] # 选取年龄大于30且城市为“北京”的行,只保留“Name”和“Salary”列 my_data[my_data$Age > 30 & my_data$City == “Beijing”, c(“Name”, “Salary”)]注意:这里的
my_data$Age > 30会生成一个与Age列等长的逻辑值向量(TRUE/FALSE),[操作符根据这个向量为TRUE的行来筛选。&表示“且”,|表示“或”。
subset()函数提供了另一种更易读的语法来实现条件筛选,特别适合复杂条件:
subset(my_data, Age > 30 & City == “Beijing”, select = c(Name, Salary))4.2 行列操作与排序函数
cbind()和rbind():按列合并和按行合并。cbind用于添加新列(变量),rbind用于添加新行(观测)。但要注意,rbind要求两个数据框的列名和结构完全相同。order():排序函数。它返回的是排序后的索引(位置),而不是直接排序数据。这是新手最容易困惑的地方。# 错误示范:这不会改变my_data order(my_data$Age) # 正确做法:用order()返回的索引来重新排列数据框 my_data_sorted <- my_data[order(my_data$Age), ] # 按年龄升序 my_data_sorted_desc <- my_data[order(-my_data$Age), ] # 按年龄降序(数值型加负号) # 多列排序:先按City升序,同City内按Age降序 my_data[order(my_data$City, -my_data$Age), ]unique():去重函数。返回向量或数据框中的唯一值。常用于检查或清理重复的观测。unique(my_data$City) # 查看有哪些独特的城市 unique(my_data) # 移除数据框中所有列完全相同的行which():查找索引函数。返回满足条件的元素位置。它和逻辑判断配合使用,威力巨大。# 找出年龄缺失(NA)的行索引 missing_age_index <- which(is.na(my_data$Age)) # 找出年龄大于100的“异常值”行索引 outlier_index <- which(my_data$Age > 100)
5. 数据转换与计算模块:让数据开口说话
数据整理好后,就该进行计算和汇总了。这个模块的函数是产生洞察的核心。
5.1 数学统计与向量化运算
R是向量化语言,一次操作就能作用于整个向量,效率极高。
- 基础运算:
+,-,*,/,^(幂),%%(取余),%/%(整除)。 - 统计函数:
sum(),mean(),median():求和、均值、中位数。处理缺失值时务必使用na.rm = TRUE参数。mean(my_data$Income, na.rm = TRUE) # 计算收入均值,忽略NAsd(),var():标准差、方差。min(),max(),range():最小值、最大值、范围。quantile():分位数。quantile(vec, probs = c(0.25, 0.75))可以计算上下四分位数。
round(),ceiling(),floor():四舍五入、向上取整、向下取整。log(),log10(),exp():自然对数、以10为底的对数、指数函数。数据标准化和转换时常用。scale():标准化函数。将数据转换为均值为0、标准差为1的分布。在回归、聚类等模型前常需进行。my_data$Income_scaled <- scale(my_data$Income)
5.2 分组汇总的利器:apply家族与tapply
当需要对矩阵、数据框的行或列,或者对数据分组进行计算时,循环for往往效率低下,apply家族是更优雅的解决方案。
apply(X, MARGIN, FUN):对数组(如矩阵)的行或列应用函数。MARGIN = 1:对每一行应用函数。MARGIN = 2:对每一列应用函数。
# 计算数据框每一列(数值型)的均值 col_means <- apply(my_data[, c(“Age”, “Income”)], 2, mean, na.rm = TRUE)lapply(X, FUN):列表应用。对列表(list)的每个元素应用函数,返回一个列表。数据框本质上也是一种列表(列是元素),所以也常用。# 获取数据框每一列的类型 col_types <- lapply(my_data, class)sapply(X, FUN):简化列表应用。它尝试将lapply的结果简化,比如返回一个向量或矩阵,更友好。# 简化版,直接返回一个字符向量 col_types_vec <- sapply(my_data, class)tapply(X, INDEX, FUN):分组应用。根据一个或多个因子(分组变量)对向量进行分组,然后对每组应用函数。这是进行“分组-汇总”的经典函数。# 计算不同城市(City)的平均年龄(Age) avg_age_by_city <- tapply(my_data$Age, my_data$City, mean, na.rm = TRUE) # 结果是一个以城市名为名的命名向量
实操心得:
apply家族初学有点绕,但它是摆脱低级循环、写出高效R代码的关键一步。先从apply和tapply练起。记住,lapply返回列表,sapply试图简化它。当你需要对数据框的每一列做相同操作时(比如检查缺失值比例),sapply非常顺手:sapply(my_data, function(x) sum(is.na(x))) # 计算每列缺失值数量
5.3 创建与转换变量
ifelse():向量化的条件判断。比写循环快得多。my_data$Age_Group <- ifelse(my_data$Age < 30, “Young”, ifelse(my_data$Age < 50, “Middle”, “Old”)) # 创建了一个新的年龄分组变量transform():在数据框内转换或添加新变量。语法更直观。my_data <- transform(my_data, Income_K = Income / 1000, # 创建千元收入变量 Log_Income = log(Income + 1)) # 创建对数收入变量(+1防0值)cut():将连续变量分箱为因子。常用于将年龄、收入等连续变量转换为分类变量。my_data$Income_Level <- cut(my_data$Income, breaks = c(0, 3000, 10000, Inf), labels = c(“Low”, “Medium”, “High”))
6. 逻辑控制与迭代模块:让代码拥有判断力
虽然R鼓励向量化操作,但理解控制流是编写灵活程序的基础。
6.1 条件判断:if、else与ifelse()
if和else:用于控制代码块的执行流程。注意if语句的条件必须是一个长度为1的逻辑值。x <- 10 if (x > 5) { print(“x is greater than 5”) } else { print(“x is 5 or less”) }注意:如果条件是一个逻辑向量(比如
my_data$Age > 30),R只会用第一个元素([1])来判断,并抛出警告。这是新手常踩的坑。要对向量的每个元素做判断,请用向量化的ifelse()。ifelse():如前所述,它是向量化的,用于创建新向量,而不是控制代码块。
6.2 循环:for、while与repeat
for (var in sequence):最常用的循环,遍历一个序列(向量、列表等)。for (i in 1:5) { print(paste(“Iteration”, i)) } # 遍历数据框的列名 for (col_name in names(my_data)) { print(paste(“Column:”, col_name)) }while (condition):当条件为真时,重复执行代码块。务必确保条件最终会变为假,否则是死循环。repeat {…}:无限循环,必须用break语句跳出。
重要建议:在R中,能向量化操作就尽量避免用循环。循环(尤其是对大数据)通常比向量化函数慢。
apply家族函数通常是替代显式for循环的更好选择。但在某些复杂的、迭代步骤间有依赖的场景下,循环仍是必要的工具。
7. 可视化入门模块:用图形探索数据
“一图胜千言”。R的基础绘图系统(graphics)功能强大,通过几个核心函数组合就能生成丰富的图形。
7.1 基础绘图函数:从散点图到直方图
plot():万能绘图函数。根据输入数据类型自动生成散点图、线图、残差图等。plot(my_data$Age, my_data$Income) # 散点图:年龄 vs 收入 plot(my_data$City) # 如果City是因子,则生成条形图关键参数:
main(主标题),xlab/ylab(坐标轴标签),col(颜色),pch(点形状),type(类型,如“l”为线,“b”为点线)。hist():绘制直方图,查看数值变量的分布。hist(my_data$Income, main = “Distribution of Income”, xlab = “Income”, col = “lightblue”)参数
breaks可以控制分组数量(柱子的粗细)。boxplot():绘制箱线图,查看分布、中位数、四分位数和异常值。boxplot(Income ~ City, data = my_data, main = “Income by City”, col = “lightgreen”) # 公式语法:Income ~ City 表示按City分组绘制Income的箱线图barplot():绘制条形图,展示分类变量的频数或汇总值。city_counts <- table(my_data$City) # 先计算频数表 barplot(city_counts, main = “Number of People by City”, ylab = “Count”)
7.2 图形控制与组合
par():图形参数设置函数。这是基础绘图系统的控制中枢,可以一次性设置全局图形参数。# 设置图形边距 (下、左、上、右) par(mar = c(5, 4, 2, 2)) # 设置一页多图 (2行2列) par(mfrow = c(2, 2)) hist(my_data$Age) boxplot(my_data$Income) plot(my_data$Age, my_data$Income) barplot(table(my_data$City))踩坑记录:
par(mfrow)设置后,之后的所有图都会按这个布局排列,直到创建新的图形设备或重置参数。忘记这一点可能导致后面的图挤在一起。可以用dev.off()关闭当前图形设备来重置,或者重新设置par(mfrow = c(1,1))。legend():添加图例。abline():添加参考线。可以添加水平线(h=)、垂直线(v=)或回归线(a=截距,b=斜率)。abline(h = mean(my_data$Income, na.rm=TRUE), col=“red”, lty=2) # 添加平均收入水平虚线
8. 实用工具模块:提升效率与排错能力
最后这个模块的函数不直接处理数据,但能极大提升你的编程效率和调试体验。
8.1 字符处理与匹配
paste()/paste0():连接字符串。paste默认用空格连接,paste0是无缝连接。name <- “Alice” age <- 30 paste(“Name:”, name, “Age:”, age) # “Name: Alice Age: 30” paste0(“ID_”, 1:5) # “ID_1” “ID_2” … “ID_5”grep(),grepl():模式匹配。在字符向量中查找匹配正则表达式的元素。grep(pattern, x):返回匹配项的索引。grepl(pattern, x):返回逻辑向量(TRUE/FALSE),表示是否匹配。
files <- c(“data1.csv”, “script.R”, “data2.csv”, “plot.pdf”) csv_files <- files[grepl(“\\.csv$”, files)] # 选取所有以.csv结尾的文件名sub(),gsub():字符串替换。sub(pattern, replacement, x):只替换第一个匹配项。gsub(pattern, replacement, x):替换所有匹配项。
text <- “Hello, world. Hello, R!” sub(“Hello”, “Hi”, text) # “Hi, world. Hello, R!” gsub(“Hello”, “Hi”, text) # “Hi, world. Hi, R!”
8.2 因子与类型处理
factor():创建或转换因子。因子是R中处理分类变量的核心数据结构,它存储了可能的类别(水平)。gender <- c(“M”, “F”, “M”, “F”, “M”) gender_factor <- factor(gender, levels = c(“F”, “M”), labels = c(“Female”, “Male”)) # 定义了水平顺序和标签as.xxx()系列:类型转换函数。如as.numeric(),as.character(),as.Date(),as.factor()。数据清洗时频繁使用。# 常见问题:数字被读成字符 my_data$Age <- as.numeric(my_data$Age) # 转换失败会变成NA,并给出警告
8.3 环境管理与帮助
ls():列出当前工作空间的所有对象。当你忘记变量名时很有用。rm():删除对象。rm(list = ls())会清空整个工作空间,使用需谨慎!getwd()/setwd():获取/设置当前工作目录。建议使用RStudio的项目(Project)功能来管理,比手动setwd更可靠。help()或?:查看函数帮助文档。?mean会打开mean函数的帮助页。学会读帮助文档是进阶的必经之路。example():运行函数示例。example(plot)会运行plot函数自带的一系列示例图,非常直观。
8.4 缺失值处理
is.na():检测缺失值。返回一个逻辑向量。sum(is.na(my_data$Age)) # 计算Age列的缺失值个数 complete.cases(my_data) # 返回一个逻辑向量,表示哪些行是完整的(无任何NA) my_data_complete <- my_data[complete.cases(my_data), ] # 删除所有含NA的行注意事项:直接对包含NA的向量做计算(如
sum(my_data$Age))会返回NA。务必记得在统计函数中使用na.rm = TRUE参数。删除缺失值 (na.omit()) 要小心,需评估是否会导致严重的信息损失或偏差。
9. 常见问题与排查技巧实录
即使掌握了函数,在实际操作中还是会遇到各种报错和意外情况。这里记录几个我踩过的高频坑和解决思路。
9.1 函数执行报错:“对象找不到”或“函数不存在”
- 错误提示:
Error: object ‘xxx’ not found或Error: could not find function “yyy” - 排查步骤:
- 检查拼写:这是最常见的原因,尤其是大小写。R是大小写敏感的,
MyData和mydata是两个不同的对象。 - 检查是否已创建/加载:用
ls()看看工作空间里有没有这个对象。对于函数,检查是否安装了对应的包并已用library()加载。 - 检查作用域:如果你在函数内部使用变量,确保它已被定义为函数的参数,或者在函数内部创建。
- 检查拼写:这是最常见的原因,尤其是大小写。R是大小写敏感的,
9.2 数据类型导致的意外行为
- 问题现象:数学计算返回
NA或奇怪的结果;逻辑比较不工作;绘图出错。 - 典型案例:
- 字符型当数值用:数据导入时,如果某列混入了非数字字符(如“N/A”、“-”),整列会被读成字符型(
chr)。此时mean()会报错。用str()检查,并用as.numeric()转换(会产生警告,非数字会变NA)。 - 因子型的陷阱:看起来像数字的列可能是因子(
Factor)。对其做计算会得到因子的水平代码,而不是数值本身。先用as.character()转成字符,再用as.numeric()转成数字。 - 逻辑比较中的NA:
NA > 5或NA == NA的结果都是NA,而不是TRUE或FALSE。这会影响条件筛选。使用which()或结合is.na()来明确处理缺失值。
- 字符型当数值用:数据导入时,如果某列混入了非数字字符(如“N/A”、“-”),整列会被读成字符型(
9.3 向量回收与维度不匹配警告
- 问题现象:对两个长度不同的向量做运算(如
c(1,2,3) + c(1,2))不报错,但会给出警告,结果可能出乎意料。 - 原因与解决:R会循环利用(回收)较短的向量来匹配较长向量的长度。
c(1,2,3) + c(1,2)等价于c(1,2,3) + c(1,2,1)。务必确保参与运算的向量长度一致或成整数倍关系,并理解回收规则。
9.4 绘图不显示或显示异常
- 问题现象:运行了绘图命令,但图形窗口没弹出;图形元素叠加混乱。
- 排查步骤:
- 图形设备:在RStudio中,图形通常显示在“Plots”面板。如果没显示,检查是否被意外关闭或隐藏。可以尝试运行
dev.new()打开新窗口。 par()参数残留:如前所述,全局图形参数(如mfrow)会影响后续所有图。在绘制新图前,用dev.off()或重新设置par(mfrow=c(1,1))来重置。- 绘图顺序:基础绘图是“画笔模型”,后绘制的图层会覆盖在先前的图层上。确保
plot()(创建新图)和points()、lines()(添加元素)的调用顺序正确。
- 图形设备:在RStudio中,图形通常显示在“Plots”面板。如果没显示,检查是否被意外关闭或隐藏。可以尝试运行
9.5 包安装与加载失败
- 问题现象:
install.packages(“xxx”)失败,或library(xxx)报错。 - 常见原因与解决:
- 网络问题:尝试更换CRAN镜像。在RStudio中,可以通过
Tools -> Global Options -> Packages更换。 - 依赖包缺失:有些包依赖其他包。安装失败信息通常会提示缺少哪个包。手动安装缺失的依赖包。
- 版本不兼容:R版本或系统环境太老/太新。检查包的文档,看其支持的R版本。
- 权限问题(尤其在Linux或公司服务器):可能没有写入默认库目录的权限。可以安装到个人目录:
.libPaths(“~/my_R_libs”);install.packages(“xxx”, lib=“~/my_R_libs”)。
- 网络问题:尝试更换CRAN镜像。在RStudio中,可以通过
掌握这50个函数,相当于掌握了R语言的一套“组合拳”。关键不在于一次性背下来,而是在实践中反复调用、遇到问题回来查阅。我建议你创建一个自己的“R函数速查笔记”,把最常用的函数、参数和用例记下来,同时记录下自己踩过的每一个坑和解决方法。随着你处理的数据集越来越复杂,你会自然地去探索更专门的包和函数,但那时,这些基础函数已经成为你思维的一部分,让你能更专注于解决实际问题,而不是纠结于语法细节。编程语言的学习曲线总是开始最陡,一旦跨过这个入门门槛,后面的路会越走越宽。