简介:《R语言期末知识点汇总》以单份docx文档整理,面向K12阶段接触编程的学生、计算机相关专业初学者以及临近课程考核的复习者,用于在短时间内串联数据分析与统计计算的核心概念。资源包共1个docx文件,约157KB,轻量易携带,便于打印或导入笔记软件逐条勾画。内容按数据结构、操作与访问、绘图与图形参数、帮助与历史、脚本与函数等模块编排,覆盖向量、矩阵、数组与数据框的创建和索引方式,matrix()的byrow填充、array()的dimensions、levels自定义排序等易错点均有说明;绘图部分梳理plot()的type=“b”、par()参数设置、col与lty、lwd、cex等控制,并归纳axis()自定义坐标轴、ann=FALSE移除默认标签等考点。目前已有198人学习,适合考前对照命令与参数查漏补缺,也可作为日常随手查阅的手册。
1. R语言期末复习:从 getwd() 到数据结构的一份知识点地图
R 区分大小写,这一点很多人是踩过坑才记住的。Getwd()报错、setwd("mydirectory")的引号漏掉、目录不存在时才发现 setwd 不会自动创建——这些在卷面上只值两分,在实验室里能耗掉半小时。这份「R语言期末知识点汇总」覆盖的范围其实很集中:向量、矩阵、数组、数据框与因子的构造和索引,工作空间与文件读写函数,字符串处理与 apply 族,par() 图形参数与自定义坐标轴,以及描述性统计和分组聚合。
它适合两类人。一类是刚入门 R、需要把 matrix() 的 byrow、array() 的 dimnames、factor() 的 order 这些参数一次性理清的初学者;另一类是有别的语言基础、想用最短时间补上 R 的索引语义和基础绘图系统的从业者。后面几章按数据结构、工作空间与函数式操作、图形参数、统计与分组四段推进,代码都能直接粘进控制台复现,不管是在 RStudio 还是在 VSCode 里配置好的 R 语言环境里跑都一样。
2. 向量、矩阵、数组与数据框的构造和索引
2.1 向量与标量:单一模式约束与位置索引
单个向量中的数据必须拥有相同的类型或模式,同一向量中无法混杂不同模式的数据。真混进一个字符,整条向量会被强制转换,数字悄悄变成字符串,后续做算术就直接报错。只含一个元素的向量就是标量,它不是独立类型,只是长度为 1 的向量,理解这一点在写函数默认值时会省很多判断。
索引从 1 开始而不是 0,方括号中的数表示给定元素中所处的位置,这一点和 C、Python 都不一样,是初学者最容易写错的地方。
v <- c(10, 20, 30, 40) v[2] # 第 2 个元素,返回 20 v[c(1, 4)] # 一次取多个位置,返回 10 40 v[-2] # 负号表示排除,返回 10 30 40 v[v > 20] # 逻辑索引,返回 30 40 mixed <- c(1, "a") # 数字被强制转为字符 class(mixed) # "character"逻辑索引和负号索引是 R 里最具辨识度的两套写法,前者可以直接把条件表达式塞进方括号,后者用来剔除元素。注意负号和正号不能混用,v[c(-1, 2)]会直接报错。
R 还把反斜杠\当作转义符,\n是新行、\t是制表符、\'是单引号、\b是退格,用在 cat() 输出和正则字符串里。写 Windows 路径时要么用正斜杠,要么写双反斜杠,否则"D:\r-course"里的\r会被当成回车。
2.2 矩阵与数组:byrow 填充方向与 dimnames 标签
矩阵由向量构造,一般格式是matrix(vector, nrow, ncol, byrow, dimnames)。其中 vector 包含矩阵的元素,nrow 和 ncol 指定行列维数,dimnames 是可选的、以字符型向量表示的行名和列名。byrow 决定按行填充(TRUE)还是按列填充(FALSE),默认情况下按列,这是默认值和直觉相反的一个参数。
m <- matrix(1:6, nrow = 2, ncol = 3, byrow = TRUE, dimnames = list(c("r1", "r2"), c("c1", "c2", "c3"))) m # c1 c2 c3 # r1 1 2 3 # r2 4 5 6 m[1, ] # 第 1 行,返回向量 m[, 2] # 第 2 列 m[1, 2] # 第 1 行第 2 列,返回标量 m["r2", "c3"] # 用行名列名索引,可读性更好省略某个维度下标就表示取整行或整列,m[1, ]返回的是向量而不是 1×3 的矩阵,这个降维行为经常导致后续%*%维度不匹配。要保留维度可以加drop = FALSE。
| 索引表达式 | 含义 | 返回类型 |
|---|---|---|
X[i, ] | 矩阵 X 的第 i 行 | 向量 |
X[, j] | 矩阵 X 的第 j 列 | 向量 |
X[i, j] | 第 i 行第 j 列的元素 | 标量 |
X[i, j, drop = FALSE] | 同上,保留矩阵结构 | 1×1 矩阵 |
a[i, j, k] | 三维数组按维度定位 | 标量或低维数组 |
数组是矩阵的推广,一般格式是array(vector, dimensions, dimnames)。vector 包含数据,dimensions 是一个数值型向量,给出各维度下标的最大值,可以是两维也可以是三维甚至更高,dimnames 是可选的、给维度名称标签的列表。
a <- array(1:8, dim = c(2, 2, 2), dimnames = list(c("r1","r2"), c("c1","c2"), c("p1","p2"))) a[1, 2, 1] # 第一个 2×2 切片里第 1 行第 2 列 a[, , "p2"] # 按名字取第二个切片维度名称在三维以上时价值最大,纯数字索引到第三层基本已经读不懂了。
2.3 数据框、因子与搜索路径
数据框是 R 里最接近「一张表」的结构,每一列可以是不同的模式,数值列和字符列能共存,这正好和矩阵的同质性要求相反。用 data.frame() 创建时,列向量长度必须一致,否则会报错。
df <- data.frame(id = 1:3, name = c("a", "b", "c"), score = c(90, 85, 77)) df$score # $ 取列 df[["score"]] # 双重括号,按名字取 df[, "score"] # 方括号加列名 attach(df) # 把数据框加入搜索路径 mean(score) # 直接写列名即可 detach(df) # 从搜索路径移除,不改动数据框本身attach() 把数据框添加到 R 的搜索路径中,写列名不用再带df$,交互式分析很省事;detach() 从搜索路径里移除它,对数据框本身不做任何处理。同一个名字在多个数据框里出现时,attach 的先后顺序会决定谁被命中,脚本里尽量别依赖它。
类别变量和有序类别变量在 R 中称为因子。函数 factor() 以一个整数向量的形式存储类别值,取值范围是 1 到 k,同时一个由字符串原始值组成的内部向量投影到这些整数上。默认排序是升序的字母序,可以指定 levels 来改变默认排序,要表示有序型变量还需要指定 order = TRUE。
f <- factor(c("low", "high", "mid"), levels = c("low", "mid", "high"), ordered = TRUE) f # [1] low high mid # Levels: low < mid < high levels(f) # 查看排序规则指定了 levels 之后,low 会排在 mid 和 high 前面,而不是按字母序把 high 顶到最前。做医学数据分析这类场景时,剂量组、分期这类变量的排序全靠 levels 控制,写错了图表和统计模型的参考水平都会跟着错。
3. 工作空间管理、字符串函数与 apply 族向量化
3.1 工作目录、对象与脚本执行
函数 getwd() 用来查看当前的工作目录,setwd() 设定当前目录,使用引号闭合目录名和文件名。setwd() 不会自动创建一个不存在的目录,路径写错只会报错,需要先用 dir.create() 把目录建出来。相对路径全部相对于工作目录,而不是脚本文件所在目录,这一点在项目里切换脚本时最容易出问题。
getwd() # 显示当前工作目录 setwd("D:/r-course/data") # 切换目录,引号必须闭合 dir.create("output") # 创建新目录 ls() # 列出当前工作空间的对象 rm(list = ls()) # 清空环境,rm 需要传入名字向量 source("clean.R") # 执行脚本;不含路径则在当前工作目录找 save(a, b, file = "objs.RData") # 保存指定对象到文件 load("objs.RData") # 读取工作空间到当前会话 q() # 退出 R,会询问是否保存工作空间source() 让脚本在当前会话中执行,脚本里定义的变量会留在全局环境里,适合把数据清洗和建模拆成多个文件串起来。ls() 只能列出名字,要看类型还得配合 class() 或者 str()。rm() 的参数是对象名组成的向量,rm(list = ls())是最常用的清空写法,执行前确认没有想留的中间结果。
| 函数 | 作用 | 默认值说明 |
|---|---|---|
getwd()/setwd() | 查看 / 设置工作目录 | 路径需用引号闭合 |
ls()/rm() | 列出 / 移除对象 | rm 需要名字向量 |
history(#) | 显示最近命令 | 默认 25 条 |
savehistory("myfile") | 保存命令历史 | 默认 .Rhistory |
loadhistory("myfile") | 载入命令历史 | 默认 .Rhistory |
save.image("myfile") | 保存整个工作空间 | 默认 .RData |
options() | 显示或设置当前选项 | 影响全局行为 |
help()/? | 显示帮助文档 | ?data.frame同效 |
命令历史用 savehistory() 和 loadhistory() 存取,默认文件名是 .Rhistory;工作空间用 save.image() 保存,默认文件名是 .RData。两者都落在当前工作目录下,切目录之后历史记录就找不着了,这也是「明明保存过却读不到」的常见原因。
3.2 输出重定向与图形设备
sink("filename") 将输出重定向到文件,对图形输出没有影响,图形走的是绘图设备那条路。参数 append = TRUE 可以把文本追加到文件后而不是覆盖它,split = TRUE 则让输出同时发送到屏幕和文件。
sink("run.log") # 开始重定向 sink("run.log", append = TRUE, split = TRUE) # 追加模式 + 屏幕同步 print(summary(1:10)) sink() # 关闭重定向,务必成对出现 pdf("plot.pdf") plot(1:10) dev.off() # 关闭设备,输出回到终端sink() 忘记配对是脚本里最常见的坑,日志文件会一直增长,屏幕却什么都看不到。dev.off() 的作用是把输出返回到终端,同时把图形文件写完整,不调用它生成的 PDF 有可能是零字节。
3.3 paste、substr、grep 与字符串处理
字符串函数在数据清洗里出现频率极高,尤其是把变量名和序号拼成文件名、从乱码里提取编号这几类操作。
x <- c("ab", "cde", "fghij") nchar(x[3]) # 5,字符数量 length(x) # 3,元素个数,两者含义不同 paste("x", 1:3, sep = "M") # "xM1" "xM2" "xM3" paste(c("a","b"), collapse = "-") # "a-b",collapse 负责合并成一条 substr("abcdef", 2, 4) # "bcd",start 到 stop 闭区间 toupper("abc") # "ABC" tolower("ABC") # "abc" grep("A", c("b", "A", "c"), fixed = TRUE) # 返回 2 sub("a", "2", "abcdef") # "2bcdef",只替换第一个 gsub("a", "2", "abac") # "2b2c",替换全部 strsplit("a,b,c", split = ",") # 返回列表 cat("Hello", "Jane", "\n") # cat 在对象之间补空格grep()、sub()、strsplit() 都带 fixed 参数:fixed = FALSE 时 pattern 按正则表达式处理,fixed = TRUE 时按纯文本字符串处理。搜索含.*(这类字符的内容时必须设 fixed = TRUE,否则.会匹配任意字符,结果看起来对但实际是错的。grep() 返回的是匹配的下标,想要匹配到的值需要加 value = TRUE。
| 函数 | 作用 | 返回 |
|---|---|---|
nchar(x) | 字符数量 | 数值向量 |
length(x) | 元素个数 | 单个数值 |
paste(..., sep, collapse) | 连接字符串 | 字符向量或单串 |
substr(x, start, stop) | 提取或替换子串 | 字符向量 |
grep(pattern, x, fixed) | 搜索模式 | 匹配下标 |
sub/gsub | 替换首个 / 全部 | 字符向量 |
strsplit(x, split) | 按分隔符切分 | 列表 |
toupper/tolower | 大小写转换 | 字符向量 |
排序相关的一步也常和字符串一起用:函数 order() 对一个数据框进行排序,默认排序顺序是升序,在排列变量前加一个减号即可得到降序的排列结果,例如df[order(-df$score), ]。sort() 返回排好序的值,order() 返回的是位置,写数据框筛选时用的是后者。
3.4 apply 族与转置
apply() 可以把一个任意函数「应用」到矩阵、数组、数据框的任何维度上,格式为apply(x, MARGIN, FUN, ...)。其中 x 为数据对象,MARGIN 是维度下标,1 表示行、2 表示列,FUN 是自定义函数,...是传递给 FUN 的额外参数。
m <- matrix(1:6, nrow = 2, byrow = TRUE) apply(m, 1, sum) # 按行求和,返回长度 2 的向量 apply(m, 2, mean) # 按列求均值,返回长度 3 的向量 apply(m, 1, function(r) r / sum(r)) # 每行做归一化 t(m) # 矩阵转置 lst <- list(a = 1:3, b = 4:6) lapply(lst, mean) # 返回列表 sapply(lst, mean) # 返回向量,能简化就简化MARGIN = 1 表示行、MARGIN = 2 表示列,这个映射关系写在参数里,记反了结果整体会错位但不会报错,只能靠结果量纲去核对。sapply() 是 lapply() 的简化版,结果能压成向量就压成向量,适合取列表里每个成分的第一个元素这类操作。t() 对矩阵或数据框做转置,转置后的数据框列类型可能被强制统一,转置前最好先确认列是否同质。
4. par() 图形参数、axis() 自定义坐标轴与统计图形
4.1 par() 的可改参数与只读列表
函数 par() 可以修改图形的参数。不加参数地执行 par() 会生成一个含有当前图形参数设置的列表,参数 no.readonly = TRUE 则生成一个可以修改当前参数的列表——默认返回的列表里有一批不能改的只读项,直接整体套用会报错。
op <- par(no.readonly = TRUE) # 先存一份当前设置 par(col.axis = "grey30", col.lab = "black", cex.axis = 0.9, cex.lab = 1.1, pch = 16, lty = 2, lwd = 1, font.main = 2, ps = 12, family = "sans") plot(1:10, type = "b") par(op) # 还原,避免污染后续图形改参数之前先存一份、画完再还原,是批量出图时的标准习惯。会话级别的 par() 设置会一直生效,忘了还原,后面几十张图全都会带着上一次的颜色和字号。
| 参数 | 控制对象 | 常用取值 |
|---|---|---|
col | 默认绘图颜色 | 颜色名或十六进制值 |
col.axis | 坐标轴刻度文字颜色 | 同上 |
col.lab | 坐标轴标签颜色 | 同上 |
col.main/col.sub | 标题 / 副标题颜色 | 同上 |
fg/bg | 图形前景色 / 背景色 | 同上 |
cex | 符号相对默认大小的缩放倍数 | 默认 1,1.5 为放大 |
cex.axis/cex.lab | 刻度文字 / 标签缩放倍数 | 0.8 到 1.2 之间 |
cex.main/cex.sub | 标题 / 副标题缩放倍数 | 同上 |
pch | 绘制点使用的符号 | 0–25 的整数 |
lty/lwd | 线条类型 / 线条宽度 | lwd 默认 1 |
font | 字体样式 | 1 常规、2 粗体、3 斜体、4 粗斜体、5 符号 |
ps/family | 字体磅值 / 字体族 | 12 为常见磅值 |
cex 是一个数值,表示绘图符号相对于默认大小的缩放倍数,默认大小为 1,1.5 表示放大为默认值的 1.5 倍,0.5 表示缩小为默认值的 50%。cex.axis、cex.lab、cex.main、cex.sub 分别控制刻度文字、坐标轴标签、标题、副标题的缩放倍数,投屏演示的图通常要把 cex.axis 提到 1.2 以上才看得清。
4.2 plot() 与 axis() 自定义坐标轴
plot() 的 type 参数控制图形类型,type = "b"表示同时绘制点和线,点和线不会互相覆盖。默认的绘图函数会自动补上标签和标题,可以通过在 plot() 语句或者单独的 par() 语句中添加 ann = FALSE 来移除它们。
创建自定义坐标轴时,应当禁用高级绘图函数自动生成的坐标轴。参数 axes = FALSE 禁用全部坐标轴,xaxt = "n" 和 yaxt = "n" 分别禁用 x 轴或 y 轴。然后调用 axis() 按需绘制,格式为axis(side, at, labels, pos, lty, col, las, tck, ...)。
plot(1:5, c(20, 45, 30, 60, 55), type = "b", axes = FALSE, ann = FALSE, xlim = c(0.5, 5.5), ylim = c(0, 70), pch = 16) axis(1, at = 1:5, labels = LETTERS[1:5], las = 2, tck = -0.02) axis(2, at = seq(0, 70, 10), las = 0, tck = -0.02) box() title(main = "main title", sub = "sub-title", xlab = "x-axis label", ylab = "y-axis label")side 是一个整数,表示在图形的哪边绘制坐标轴,1 是下、2 是左、3 是上、4 是右;at 是数值型向量,表示需要绘制刻度线的位置;labels 是字符型向量,表示置于刻度线旁边的文字标签,如果为 NULL 则直接使用 at 中的值;pos 指定坐标轴线绘制位置的坐标;las 控制标签是否平行于(= 0)还是垂直于(= 2)坐标轴;tck 是刻度线长度,以相对于绘图区域大小的分数表示,负值在图形外侧、正值在内侧、0 表示禁用刻度线、1 表示绘制网格线,默认值为 -0.01。
标题和标签用 title() 统一加,调用格式为title(main, sub, xlab, ylab)。分两步走的好处是坐标轴位置、刻度密度、标签朝向都能单独调,一次成图很难同时满足期刊和 PPT 两种输出要求。
4.3 条形图、饼图与直方图
条形图用barplot(height),height 可以是向量或矩阵,选项 horiz = TRUE 会生成水平条形图。如果 height 是矩阵而不是向量,结果将是一幅堆砌条形图或分组条形图:beside = FALSE(默认值)时矩阵中的每一列生成图中的一个条形,各列中的值给出堆砌的「子条」高度;beside = TRUE 时每一列表示一个分组,各列的值并列而不是堆砌。
饼图用pie(x, labels),x 是一个非负值向量,表示每个扇形的面积。扇形图还可以通过 fan.plot() 函数实现,标签重叠时比饼图更容易读。
直方图用hist(x),x 是由数据值组成的数值向量。参数 freq = FALSE 表示根据概率密度而不是频数绘制图形,参数 breaks 用于控制组的数量。
counts <- matrix(c(3, 5, 2, 6, 4, 7), nrow = 2) barplot(counts, beside = TRUE, col = c("grey70", "grey40"), names.arg = c("A", "B", "C"), legend.text = c("g1", "g2")) pie(c(30, 20, 50), labels = c("A", "B", "C")) hist(rnorm(500), freq = FALSE, breaks = 20, col = "grey85") lines(density(rnorm(500)), lwd = 2) # 叠加密度曲线breaks 给单个数字时 R 只当作建议值,实际分组数会按「美观」原则微调,要精确控制分组得传一个切点向量。堆砌和分组只差一个 beside 参数,但表达的含义完全不同,前者强调构成比例,后者强调组间对比,选错了图会误导读者。使用数据整合函数把均值、中位数、标准差这类汇总结果传给 barplot(),就能直接画出带误差信息的条形图。
5. 缺失值处理、scale() 标准化与 aggregate() 分组聚合
5.1 NA、NaN 与 na.rm
在 R 中,缺失值以符号 NA 表示,不可能出现的值通过符号 NaN 来表示,两者不是一回事:NA 是「不知道」,NaN 是「算不出来」,比如 0/0。is.na() 可以检测缺失值是否存在,它对 NA 和 NaN 都返回 TRUE。
x <- c(1, 2, NA, 4) mean(x) # 返回 NA mean(x, na.rm = TRUE) # 3.5,先移除缺失值再计算 sum(x, na.rm = TRUE) is.na(x) # FALSE FALSE TRUE FALSE df <- data.frame(a = c(1, NA, 3), b = c("x", "y", NA)) df2 <- na.omit(df) # 移除含有缺失值的整行观测 nrow(df2) # 1na.rm = TRUE 选项可以在计算之前移除缺失值并使用剩余值进行计算,几乎每个统计函数都支持它。na.omit() 移除所含缺失值的观测即行,返回的是整行被删掉之后的数据框,样本量会跟着下降,做回归前先看一眼nrow的变化。绝对中位差 mad()、值域 range()、滞后差分 diff(x, lag = n) 这类函数同样受缺失值影响,lag 用于指定滞后几项。
5.2 scale() 标准化与横向合并
默认情况下,函数 scale() 对矩阵或者数据框的指定列进行均值为 0、标准差为 1 的标准化,格式为scale(x, center = TRUE, scale = TRUE)。要对每一列做任意均值和标准差的标准化,可以按下面的方式换算。
mydate <- c(10, 20, 30, 40, 50) z <- scale(mydate) # 均值 0,标准差 1 newdate <- scale(mydate) * 8 + 60 # 想要的 SD = 8,均值 M = 60 df$score_z <- scale(df$score) # 为数据框新增标准化列 scale(df[, c("score", "age")]) # 一次标准化多列在非数值型的列上使用 scale() 函数会直接报错,所以要么先选列要么先转类型。乘上目标标准差再加上目标均值,就是逆变换回原始量纲的过程,做机器学习特征工程时这套写法比手动写(x - mean(x)) / sd(x)更不容易出错。
横向合并两个数据框用merge(dataframeA, dataframeB, by = "ID"),按公共索引对齐。如果要直接横向合并两个矩阵或者数据框、并且不需要指定公共索引,可以直接使用 cbind(),但每个对象必须拥有相同的行数并且要以相同的顺序排序;纵向合并用 rbind()。cbind() 不做匹配检查,行序错位不会有任何提示,这一点和 merge() 的差别必须记牢。生成序列用seq(from, to, by),例如 seq(1, 10, 2) 返回 c(1, 3, 5, 7, 9);重复用rep(x, n)。
5.3 aggregate() 与 by() 分组,以及一个分段函数的写法
使用 aggregate() 函数来分组获取描述性统计量,该函数仅允许在每次调用中使用平均数、标准差这样的单返回值函数,无法一次返回若干个统计量。要一次拿多个指标就换 by() 函数,格式为by(data, INDICES, FUN),其中 data 是数据框或矩阵,INDICES 是因子或因子组成的列表,定义了分组,FUN 是任意函数。
aggregate(df$score, by = list(df$sex), FUN = mean) # 单返回值 by(df[, c("score", "age")], df$sex, summary) # 多返回值 fun <- function(x) { y <- numeric(length(x)) y[x < -3] <- x[x < -3]^2 y[x >= -3 & x < 2] <- x[x >= -3 & x < 2] y[x >= 2] <- 3 y } x <- c(-4, -3, 0, 1, 2, 2.5, 3) cat("fun=", fun(x), "\n")分段函数的关键是先用numeric(length(x))建好同长度的容器,再按条件逐段赋值,最后一次性返回。条件必须互斥且覆盖整个定义域,如果某段没写,对应位置会留 0,而 0 在图上看起来和真实的函数值没区别,排查起来很费时间。写完贴一段测试输入,把边界值 -3 和 2 都放进去,比目测代码可靠得多。
如果还要更细的描述性统计量,stat.desc() 的格式为stat.desc(x, basic = TRUE, desc = TRUE, norm = FALSE, p = 0.95)。basic = TRUE(默认值)计算所有值、空值、缺失值的数量以及最小值、最大值、值域和总和;desc = TRUE(默认值)计算中位数、平均值、平均数的标准误、平均数置信度为 95% 的置信区间、方差、标准差以及变异系数;norm = TRUE 时额外返回正态分布统计量,包含偏度和峰度。describe() 函数则返回变量和观测的数量、缺失值和唯一值的数目、平均值、分位数以及五个最大和五个最小的值,用来快速摸清一列数据的长相特别顺手。
本文还有配套的精品资源,点击获取