主要内容:
- 三种 subset 操作
- 六类 subset
- 不同对象的的重要区别
众所周知,R 语言里面有几种不同的 subset 方法:[]
,[[]]
,$
,但是有时候会产生混淆。所以这篇笔记主要分析理清 R 语言里面的 subset 操作。
来让我们用 []
来 subset!
对 atomic vector 进行 subset 操作时,通常使用 []
,总共有 6 种形式:
-
正数:简单,就是返回这个位置上的数(注意 R 语言从 1 开始计数)
-
负数:忽略这个位置上的数
-
逻辑值:只选择那些值为
TRUE
的数,所以基于此可以在[]
中放入某些逻辑判断条件x[c(TRUE, FALSE, TRUE)] x[x > 3]
-
什么也没有:返回原始的 vector
-
0:返回一个长度为 0 的 vector
-
字符:如果 vector 设置好了 name,就可以使用字符型进行 subset
y <- setNames(x, letters[1:4]) y[c("d", "c", "a")]
对于 list 来说,subset 可以有两种:使用 []
往往会返回一个 list,使用 [[]]
和 $
则会得到 list 的组成部分。
对于 data frame 来说,它兼具两种数据结构的特点:使用一个 vector 对其 subset,它就可以当做 list;使用两个 vector 对其 subset,它就可以当做 matrix。
df <- data.frame(
x = 1:3,
y = 3:1,
z = letters[1:3]
)
df[1:2]
# x y
# 1 1 3
# 2 2 2
# 3 3 1
df[1:2, ]
# x y z
# 1 1 3 a
# 2 2 2 b
还有两种操作:[[]]
和 $
前面提到 [[]]
这种方式对于 list 来说,会从里面取出它的元素。这里可以引申出简化操作和保留操作的概念。
顾名思义,保留操作会保证输出和输入的数据结构类型是一样的,而简化操作会对输入进行不同程度的简化:
- Atomic vector:移除变量名字
- List:返回的是 list 里的元素,而不是 list
- Factor: 舍弃没有出现的 level
- Matrix:如果某个维度长度是 1,舍弃这个维度
- Data frame:如果输出一个单变量,把它变成一个 vector
Simplifying | Preserving | |
---|---|---|
Vector | x[[1]] |
x[1] |
List | x[[1]] |
x[1] |
Factor | x[1:4, drop=T] |
x[1:4] |
Array | x[1, ] x[, 1] |
x[1, , drop=F] x[, 1, drop=F] |
Data frame | x[, 1] x[[1]] |
x[, 1, drop=F] x[1] |
$
在某种方面上和 [[]]
一样,它经常被用来从一个 data frame 种提取变量,如 mtcars$cyl
等。
$
和 [[]]
有一些区别:
-
不能这样使用
$
(但[[]]
可以):var <- cyl mtcars$var
-
$
可以进行名字检索:mod <- lm(mpg ~ wt, data = mtcars) mod$df.r # 返回 mod$df.residual
应用
对字符缩写的转换(本质上是对分类变量设置了标签):
x <- c("m", "f", "m", "m", "f", "u")
lookup <- c(m="Male", f="Female", u="Unknown")
lookup[x]
# m f m m f u
# "Male" "Female" "Male" "Male" "Female" "Unknown"
info
是关于成绩的相关信息,我们可以使用 integer subset 进行信息的匹配和合并:
grades <- c(1, 2, 3, 3, 1)
info = data.frame(
grade = 1:3,
desc = c("Excellent", "Good", "Poor"),
fail = c(F, F, T)
)
// 使用 match
id <- match(grades, info$grade)
info[id, ]
// 使用 rownames
rownames(info) <- info$grade
info[grades, ]
Data frame 对行进行随机抽样:
df <- data.frame(
x = rep(1:3, each=2),
y = 6:1,
z = letters[1:6]
)
df[sample(nrow(df)), ]
df[sample(nrow(df), 8, rep = T), ]
n
列表示了每个观测重复几次,这里相当于把频数表转换为原始数据:
df <- data.frame(x = c(2, 4, 1), y = c(9, 11, 6), n = c(3, 5, 1))
df[rep(1:nrow(df), df$n), ]
使用布尔值的 subset 可以让我们在 data frame 中进行条件筛选:
- 注意和
if
中使用的&&
和||
不同,这里使用的是&
和|
- 如果有很多条件,不想重复写 data frame 的名字,可以使用
subset
mtcars[mtcars$gear == 5 & mtcars$cyl == 4, ]
subset(mtcars, gear == 5 & cyl == 4)