我经常发现自己使用
for
循环来执行涉及多个数据帧的按行操作,如下例所示:
# Sample data
set.seed(123)
df1 <- data.frame(a = sample(1:100, size = 20), b = sample(letters, size = 20))
df2 <- data.frame(c = sample(1:100, size = 20), d = sample(letters, size = 20))
# Sample loop operation
for (i in 1:nrow(df2)){
number.2 <- df2$c[i]
letter.1 <- df1$b[df1$a == number.2]
df2$x[i] <- ifelse(!is_empty(letter.1), paste0(letter.1), paste0("No match"))
}
代码做了我想要的,我只是怀疑有一种更优雅的方法来使用
apply
。
有没有办法使用
apply
函数系列来做到这一点?
使用
left_join
:注意 - 比较您的 x
列和 b
列
left_join(df2, df1, join_by(c == a)) %>%
mutate(b = replace_na(b, 'No match'))
c d x b
1 89 v No match No match
2 34 z No match No match
3 93 g No match No match
4 69 p p p
5 72 q x x
6 76 r No match No match
7 63 y No match No match
8 13 b No match No match
9 82 d No match No match
10 91 m No match No match
11 25 e w w
12 38 f No match No match
13 21 c No match No match
14 79 i q q
15 41 u No match No match
16 47 o No match No match
17 60 t No match No match
18 16 j No match No match
19 6 x No match No match
20 96 n No match No match
您在这里所得到的是编写通用操作的很长的方法。这是使用
match()
的单行代码,或者您可以使用 merge
或 dplyr
的 join
函数之一使其更通用,适用于更多种类的案例和列。
当您匹配一个值时,match
效果很好。如果您要匹配多列,则 merge
或 join
效果很好。如果您有更复杂的条件,例如 >=
而不是 ==
,那么您需要“非等值连接”,这在 dplyr
或 data.table
中得到支持。
df2$result = df1[match(df2$c, df1$a), "b"]
df2
# c d x result
# 1 89 v No match <NA>
# 2 34 z No match <NA>
# 3 93 g No match <NA>
# 4 69 p p p
# 5 72 q x x
# 6 76 r No match <NA>
# 7 63 y No match <NA>
# 8 13 b No match <NA>
# 9 82 d No match <NA>
# 10 91 m No match <NA>
# 11 25 e w w
# 12 38 f No match <NA>
# 13 21 c No match <NA>
# 14 79 i q q
# 15 41 u No match <NA>
# 16 47 o No match <NA>
# 17 60 t No match <NA>
# 18 16 j No match <NA>
# 19 6 x No match <NA>
# 20 96 n No match <NA>
另一个基本 R 选项,带有
merge
transform(
merge(df2, df1, by.x = "c", by.y = "a", all.x = TRUE),
x = ifelse(is.na(b), "No Match", b)
)[-3]
这给出了
c d x
1 6 x No Match
2 13 b No Match
3 16 j No Match
4 21 c No Match
5 25 e w
6 34 z No Match
7 38 f No Match
8 41 u No Match
9 47 o No Match
10 60 t No Match
11 63 y No Match
12 69 p p
13 72 q x
14 76 r No Match
15 79 i q
16 82 d No Match
17 89 v No Match
18 91 m No Match
19 93 g No Match
20 96 n No Match