写在前面
紧接上一版,分两版的目的是,一号是初级,二号是进阶。(写太长了,容易让人丧失阅读兴趣)
1.提取单一成分
[[
用于提取单一成分,而x$y
是x[["y"]]的简写。
1.1 [[
[
作用于列表时,会返回一个更小的列表,而[[
能提取元素。
示例:
x <- list(1:3, "a", 4:6)
书中以火车的车厢进行了举例。
image.png
当提取多个元素的时候:
image.png
x[[c(1, 2)]]
等同于x[[1]][[2]]
。
> x[[c(1, 2)]]
[1] 2
> x[[1]][[2]]
[1] 2
1.2 $
x$y`是x[["y"]]的简写。
示例
var <- "cyl"
mtcars$var
#> NULL
mtcars[[var]]
#> [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
#上条命令也就等同于
> mtcars[["cyl"]]
[1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
[[
和$
一个不同点是,$
支持部分匹配,如
x <- list(abc = 1)
x$a
#> [1] 1
x[["a"]]
#> NULL
为了提醒读者发生了部分匹配,作者建议使用options(warnPartialMatchDollar = TRUE)
。
options(warnPartialMatchDollar = TRUE)
x$a
#> Warning in x$a: partial match of 'a' to 'abc'
#> [1] 1
1.3 丢失和超出界限的指数
[purrr::pluck()]
和[purrr::chuck()]
的引入。
x <- list(
a = list(1, 2, 3),
b = list(3, 4, 5)
)
purrr::pluck(x, "a", 1)
#> [1] 1
purrr::pluck(x, "c", 1)
#> NULL
purrr::pluck(x, "c", 1, .default = NA)
#> [1] NA
2.子集和再赋值
再赋值的基本格式是x[i] <- value
。
x <- 1:5
x[c(1, 2)] <- c(101, 102)
x
#> [1] 101 102 3 4 5
可以使用x[[i]] <- NULL
来移去列表的子集;而要添加一个字面意义上的“NULL”,则x[i] <- list(NULL)
。
x <- list(a = 1, b = 2)
x[["b"]] <- NULL
str(x)
#> List of 1
#> $ a: num 1
y <- list(a = 1, b = 2)
y["b"] <- list(NULL)
str(y)
#> List of 2
#> $ a: num 1
#> $ b: NULL
3. 应用
3.1 查询表(字符匹配)
x <- c("m", "f", "u", "f", "f", "m", "m")
lookup <- c(m = "Male", f = "Female", u = NA)
lookup[x]
#> m f u f f m m
#> "Male" "Female" NA "Female" "Female" "Male" "Male"
如果想在输出结果中去掉名字,则使用unname()
。
unname(lookup[x])
#> [1] "Male" "Female" NA "Female" "Female" "Male" "Male"
3.2 匹配相同的
示例:
grades <- c(1, 2, 2, 3, 1)
info <- data.frame(
grade = 3:1,
desc = c("Excellent", "Good", "Poor"),
fail = c(F, F, T)
)
假设我们手里有一些成绩(grades),我们想知道这些成绩对应的评价(info)是什么,我们可以使用match()
来获取grades在info的位置。
id <- match(grades, info$grade)
id
#> [1] 3 2 2 1 3
根据位置提取元素。
info[id, ]
#> grade desc fail
#> 3 1 Poor TRUE
#> 2 2 Good FALSE
#> 2.1 2 Good FALSE
#> 1 3 Excellent FALSE
#> 3.1 1 Poor TRUE
3.3 排序
x <- c("b", "c", "a")
order(x)
#> [1] 3 1 2
x[order(x)]
#> [1] "a" "b" "c"
如果要打破顺序,可以用decreasing = TRUE
;默认情况下,NA会排在末尾,可以设置na.last=NA
将NA去掉;或者设置na.last=F
,将其排在前面。
如果要将数据框的某一行内容复制多次,可以借助rep()
来实现。
df <- data.frame(x = c(2, 4, 1), y = c(9, 11, 6), n = c(3, 5, 1))
rep(1:nrow(df), df$n) #分别复制1、2、3,3次、5次、1次。
#> [1] 1 1 1 2 2 2 2 2 3
df[rep(1:nrow(df), df$n), ]
#> x y n
#> 1 2 9 3
#> 1.1 2 9 3
#> 1.2 2 9 3
#> 2 4 11 5
#> 2.1 4 11 5
#> 2.2 4 11 5
#> 2.3 4 11 5
#> 2.4 4 11 5
#> 3 1 6 1
3.4 移去数据框的某列
- 通过赋值
NULL
来删除。
df <- data.frame(x = 1:3, y = 3:1, z = letters[1:3])
df$z <- NULL
- 只提取想要的列。
df <- data.frame(x = 1:3, y = 3:1, z = letters[1:3])
df[c("x", "y")]
#> x y
#> 1 1 3
#> 2 2 2
#> 3 3 1
排除掉不想要的列。
df[setdiff(names(df), "z")]
#> x y
#> 1 1 3
#> 2 2 2
#> 3 3 1
3.5 基于条件的选择行
通过设定列的值来选取行内容。
mtcars[mtcars$gear == 5, ]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Porsche 914-2 26.0 4 120.3 91 4.43 2.14 16.7 0 1 5 2
#> Lotus Europa 30.4 4 95.1 113 3.77 1.51 16.9 1 1 5 2
#> Ford Pantera L 15.8 8 351.0 264 4.22 3.17 14.5 0 1 5 4
#> Ferrari Dino 19.7 6 145.0 175 3.62 2.77 15.5 0 1 5 6
#> Maserati Bora 15.0 8 301.0 335 3.54 3.57 14.6 0 1 5 8
mtcars[mtcars$gear == 5 & mtcars$cyl == 4, ]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Porsche 914-2 26.0 4 120.3 91 4.43 2.14 16.7 0 1 5 2
#> Lotus Europa 30.4 4 95.1 113 3.77 1.51 16.9 1 1 5 2
&
,|
的使用。
- !(X & Y) is the same as !X | !Y
- !(X | Y) is the same as !X & !Y
3.6 逻辑赋值
which()
快速找到第一个或最后一个“T”;在面对较少的“T”和较多的“F”时也同样发挥作用。
x <- sample(10) < 4
which(x)
#> [1] 2 3 4
通过定义函数的方式找到“TRUE”并重新赋值。
unwhich <- function(x, n) {
out <- rep_len(FALSE, n)
out[x] <- TRUE
out
}
unwhich(which(x), 10)
#> [1] FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
输出满足条件的向量,%%
意为整除。
(x1 <- 1:10 %% 2 == 0)
#> [1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
(x2 <- which(x1))
#> [1] 2 4 6 8 10
(y1 <- 1:10 %% 5 == 0)
#> [1] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE
(y2 <- which(y1))
#> [1] 5 10
取X和Y的交集;输出交集的元素。
# X & Y <-> intersect(x, y)
x1 & y1
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
intersect(x2, y2)
#> [1] 10
取X和Y的并集;输出并集的元素。
# X | Y <-> union(x, y)
x1 | y1
#> [1] FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE FALSE TRUE
union(x2, y2)
#> [1] 2 4 6 8 10 5
取x和Y补集的交集
# X & !Y <-> setdiff(x, y)
x1 & !y1
#> [1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE FALSE
setdiff(x2, y2)
#> [1] 2 4 6 8
去掉X、Y并集与X、Y交集的交集。
# xor(X, Y) <-> setdiff(union(x, y), intersect(x, y))
xor(x1, y1)
#> [1] FALSE TRUE FALSE TRUE TRUE TRUE FALSE TRUE FALSE FALSE
setdiff(union(x2, y2), intersect(x2, y2))
#> [1] 2 4 6 8 5
Short
-
Positive integers select elements at specific positions, negative integers drop elements; logical vectors keep elements at positions corresponding to
TRUE
; character vectors select elements with matching names. -
[
selects sub-lists: it always returns a list. If you use it with a single positive integer, it returns a list of length one.[[
selects an element within a list.$
is a convenient shorthand:x$y
is equivalent tox[["y"]]
. -
Use
drop = FALSE
if you are subsetting a matrix, array, or data frame and you want to preserve the original dimensions. You should almost always use it when subsetting inside a function. -
If
x
is a matrix,x[] <- 0
will replace every element with 0, keeping the same number of rows and columns. In contrast,x <- 0
completely replaces the matrix with the value 0. -
A named character vector can act as a simple lookup table:
c(x = 1, y = 2, z = 3)[c("y", "z", "x")]
网友评论