1 向量
向量是一维、同类型数据的容器,例如全部是数值、全部是字符,或者全部是逻辑值。
这种统一的数据类型让向量在计算时更高效,也更容易进行批量操作。比如,对一个数值向量可以直接做加减乘除,对一个字符向量可以进行拼接和匹配。由于向量在 R 里非常常用,很多更复杂的数据对象,实际上都可以看作是建立在向量基础上的。
在实际编程中,向量常用于存储一组观测值、特征值或标签。例如,温度记录、学生成绩、基因表达值等,都可以用向量来表示。
理解向量的概念,是进一步学习 R 数据处理和统计分析的基础。
1.1 创建向量
1.2 向量索引
R中向量的索引是从1开始的,可以使用方括号[]来访问向量中的元素。如果对向量各个元素进行了命名,那么也可以通过名称来访问元素,例如x["name"]。
x[1] # 访问第一个元素[1] 10
x[2:4] # 访问第二到第四个元素[1] 20 30 40
C
30
x[["C"]] # 通过名称访问元素,返回元素本身[1] 30
[]与[[]]
在 R 里,[] 和 [[]] 都用于取子集,但含义不同。z
[]是“取子集”,返回的通常还是原来的容器类型。比如对向量、列表、数据框使用[],得到的仍然是一个向量、列表或数据框的子集,而不是单个元素本身。[[]]是“取单个元素”,直接把元素拿出来。它常用于列表和数据框列,返回的是元素本身,而不是外层容器。
简单理解:
[]:保留“盒子”,例如x[1]取子集,返回一个长度为1的向量,仍然是一个“盒子”。[[]]:拆开“盒子”,拿出里面那一个对象,例如x[[1]]直接返回第一个元素的值,不再是一个向量。
1.3 逻辑向量
逻辑向量是由 TRUE 和 FALSE 组成的向量,常用于条件判断和筛选数据。它们在 R 中非常重要,因为很多函数和操作都依赖于逻辑向量来实现过滤、子集选择和条件计算。
- 通过比较运算符(如
>,<,==,!=等)生成逻辑向量。例如,x > 30会返回一个与x长度相同的逻辑向量,表示每个元素是否大于30。 - 通过逻辑运算符(如
&,|,!)进行组合。例如,(x > 20) & (x < 40)会返回一个逻辑向量,表示哪些元素同时满足大于20且小于40的条件。 - 通过
%in%运算符检查该符号左边的元素是否属于符号右侧的向量中。例如,x %in% c(20, 30)会返回一个逻辑向量,表示哪些元素是20或30。 -
==运算符用于比较元素是否相等,返回一个逻辑向量。例如,x == 30会返回一个逻辑向量,表示哪些元素等于30。
1.4 向量有关的函数
-
names(x) = NULL:去掉向量的名称属性。 -
length(x):返回向量的长度。 -
sort(x):对向量进行排序,默认升序。decreasing = TRUE参数可以指定降序。 -
order(x):返回向量元素排序后的索引位置。
1.5 向量化思维
向量化思维是 R 里非常重要的一种编程方式。它的核心思想是:尽量把对单个元素的操作,改写成对整个向量的批量操作。这样不仅代码更简洁,也通常更高效,因为 R 本身对向量运算做了很多优化。
例如,与其用循环逐个处理每个数值,不如直接对整个向量做加减乘除、比较、筛选或转换。很多常见任务都可以直接用向量化写法完成,比如计算一组成绩的平方、判断哪些值大于某个阈值,或者对一列数据统一做标准化。
理解向量化思维,有助于写出更符合 R 风格的代码。初学者常常先想到 for 循环,但在 R 中,优先考虑向量运算往往是更自然的选择。它能减少重复代码,也让程序更容易读懂和维护。
2 矩阵
矩阵是二维、同类型数据的容器,可以看作是向量的扩展。矩阵中的元素必须是同一类型(数值、字符或逻辑),但它们被组织成行和列的结构。
2.1 创建矩阵
2.2 矩阵索引
m[2, ] # 访问第二行所有列[1] 39 87 82 85
m[, 3] # 访问第三列所有行[1] 14 82 59
m[2:3, ] # 访问第二行和第三行所有列 [,1] [,2] [,3] [,4]
[1,] 39 87 82 85
[2,] 1 43 59 21
m[2:3, c(1, 4)] # 访问第二行和第三行的第一列和第四列 [,1] [,2]
[1,] 39 85
[2,] 1 21
m[m > 70] # 访问矩阵中大于70的元素[1] 87 82 85
2.3 矩阵运算
矩阵支持各种数学运算,例如加法、乘法、转置等。矩阵运算通常遵循线性代数的规则,可以用于数据分析、统计建模和机器学习等领域。
-
+,-,*,/: 两个同型矩阵, 对应元素分别做四则运算。 -
%*%: 矩阵乘法。
2.4 矩阵有关的函数
m1 <- m[, -4] # 去掉第四列,得到一个新的矩阵
diag(m1) # 提取矩阵的对角线元素[1] 68 87 59
solve(m1) # 计算拟矩阵 [,1] [,2] [,3]
[1,] 0.02865038 -0.02503120 0.02799073
[2,] -0.03956142 0.07127830 -0.08967730
[3,] 0.02834730 -0.05152434 0.08183277
eigen(m1) # 计算矩阵的特征值和特征向量eigen() decomposition
$values
[1] 147.428404 60.257792 6.313803
$vectors
[,1] [,2] [,3]
[1,] -0.4193271 -0.90673975 0.2747165
[2,] -0.8145532 0.03338313 -0.7474673
[3,] -0.4008340 0.42036722 0.6048335
3 列表
列表是R中一种灵活的数据结构,可以包含不同类型的元素,包括向量、矩阵、数据框等。列表中的每个元素都可以有自己独特的属性和结构。
列表中的每个元素都可以拥有自己独立的长度、类型和属性,因此它不像矩阵那样要求所有元素规则排列。正因为如此,列表常被用来保存模型结果、统计分析输出或多部分数据集。通过列表,用户可以更方便地把相关内容组合在一起,并按名称或位置对元素进行访问和管理。
3.1 创建列表
3.2 访问列表
- 与 Section 1.2 中介绍的向量索引类似,列表也可以通过位置或名称来访问元素。使用单方括号
[]返回的是一个子列表,而使用双方括号[[]]则直接返回元素本身。 -
unlist()函数可以将列表平摊开,转换成一个向量。 -
str()函数可以查看列表的结构,帮助理解列表中各个元素的类型和内容。
l1[2] # 返回一个包含第二个元素的子列表$b
[1] TRUE FALSE
l1[[2]] # 直接返回第二个元素,即逻辑向量[1] TRUE FALSE
4 数据框
数据框,是由列向量组成、有着矩阵形式的列表:行对应观测(记录),列对应变量(特征)。与纯矩阵不同,数据框允许不同列有不同的数据类型(数值、字符、因子/分类、日期等),并通常带有列名和可选的行名。
在R中,更建议使用现代的数据框格式tibble,它是 data.frame 的增强版本,提供了更友好的打印输出、更严格的类型检查和更方便的数据操作功能。
[]、[[]]和$等方式访问数据框中的列或元素。# A tibble: 3 × 4
ID name height weight
<int> <chr> <dbl> <dbl>
1 1 Alice 165 55
2 2 Bob 180 75
3 3 Charlie 175 68
# 按行创建
df2 <- tribble(
~ID, ~name, ~height, ~weight,
1, "Alice", 165, 55,
2, "Bob", 180, 75,
3, "Charlie", 175, 68
)
df2# A tibble: 3 × 4
ID name height weight
<dbl> <chr> <dbl> <dbl>
1 1 Alice 165 55
2 2 Bob 180 75
3 3 Charlie 175 68
5 因子
因子是R中用于处理分类数据的一种特殊数据类型。它本质上是一个整数向量,每个整数对应一个类别(水平),并且有一个关联的字符向量存储这些类别的名称。因子在统计建模和数据分析中非常重要,因为它们可以帮助我们正确地处理分类变量,并且在某些模型中,因子会被自动识别为分类特征。
- 通过
factor()函数创建因子,可以指定类别的水平和顺序。levels参数可以用来定义因子的水平,ordered参数可以指定是否为有序因子,labels参数可以用来为水平指定标签。 - 使用
cut(x, breaks, labels, ...)函数可以将连续变量转换为因子,常用于分组和分类。
[1] Fair Pass Excellent Excellent Good
Levels: Pass < Fair < Good < Excellent
[1] 及格 不及格 良 优 优
Levels: 不及格 及格 良 优
forcats 包提供了一系列函数来创建和操作因子,使得处理分类数据更加方便和高效。通过使用 forcats,我们可以轻松地重新编码因子水平、调整水平的顺序、合并水平等,从而更好地适应数据分析的需求。
-
fct_recode():修改因子水平。它适合做术语统一(比如把"M"/"F"改成"Male"/"Female")。常见坑是:旧水平名写错时不会按你预期重命名,结果可能保留原值或变成缺失,建议先检查levels()。 -
fct_collapse():折叠因子水平。比如把"Excellent"、"Good"合并为"High"。这一步常用于减少类别稀疏、提高汇总可读性。与fct_recode()的区别是:recode是“改名字”,collapse是“并组”。 -
fct_lump_*():合并少数水平到“其它”。典型作用是把低频水平归到"Other",避免长尾类别把图表和模型搞得很碎。你可以按频数阈值、前n个、比例等规则保留主要类别。 -
fct_reorder():重排序水平(常用于可视化),特别适合柱状图/箱线图,让类别按均值、中位数或其他统计量排序,而不是按字母顺序。这样可视化会更符合读者认知。
6 字符串
stringr包提供了一系列接口一致的、简单易用的字符串操作函数,足以代替R自带字符串函数。
[1] "banana_1" "apple_2" "pear_3"
str_c(x, 1:3, collapse = "_") # 将字符串与数字结合,并将结果合并成一个字符串,使用下划线分隔[1] "banana1_apple2_pear3"
str_c(x, collapse = ", ") # 将字符串向量合并成一个字符串,使用逗号和空格分隔[1] "banana, apple, pear"
# 格式化输出-把变量嵌入固定的字符串模版中
str_glue("Pi = {pi}") # 使用 str_glue 格式化字符串,插入变量值Pi = 3.14159265358979
df <- mtcars[1:2,]
str_glue_data(df, "The {rownames(df)} 总功率为 {hp} kW.") # 使用 str_glue_data 格式化字符串,插入数据框中的变量值The Mazda RX4 总功率为 110 kW.
The Mazda RX4 Wag 总功率为 110 kW.
# 查找匹配-字符串模式匹配和提取
str_detect(x, "e") # 检测字符串中是否包含字母 "e"[1] FALSE TRUE TRUE
str_extract(x, "e") # 提取字符串中第一个匹配的字母 "e"[1] NA "e" "e"
# 字符串拆分
x <- "10, 8, 7"
str_split(x, ", ") # 将字符串按逗号和空格分隔成一个列表[[1]]
[1] "10" "8" "7"
str_split_1(x, ", ") # 将字符串按逗号和空格分隔成一个向量[1] "10" "8" "7"
7 时间日期
lubridate 包提供了一系列更方便的函数,生成、转换、管理日期时间数据,足以代替 R 自带的日期时间函数。
today() # 获取当前日期[1] "2026-04-29"
now() # 获取当前日期和时间[1] "2026-04-29 15:43:38 CST"
[1] "2024-01-01" "2025-08-15" "2026-09-30"
[1] 2024 2025 2026
quarter(x1) # 提取季度[1] 1 3 3
wday(x1, label = TRUE) # 提取星期几,label = TRUE 返回星期名称[1] 周一 周五 周三
Levels: 周日 < 周一 < 周二 < 周三 < 周四 < 周五 < 周六
hour(t1) # 提取小时[1] 12
# 日期时间运算
x1 + 10 # 日期加上10天,即得到10天后的日期[1] "2024-01-11" "2025-08-25" "2026-10-10"
[1] "2024-03-01" "2025-10-15" "2026-11-30"
rollbackward(x1, roll_to_first = TRUE) # 回滚到当月第一天[1] "2024-01-01" "2025-08-01" "2026-09-01"
round_date(t1, "hour") # 将日期时间四舍五入到最近的小时。[1] "2024-01-01 12:00:00 UTC"
floor_date(t1, "hour") # 将日期时间向下取整到最近的小时。[1] "2024-01-01 12:00:00 UTC"
ceiling_date(t1, "hour") # 将日期时间向上取整到最近的小时。[1] "2024-01-01 12:00:00 UTC"
[1] 1998-11-10 UTC--2026-04-29 UTC
as.period(gap) # 将时间区间转换为周期对象[1] "27y 5m 19d 0H 0M 0S"
[1] 27
x1 %within% gap # 判断日期 x1 是否在时间区间 gap 内,返回一个逻辑值[1] TRUE TRUE FALSE