M--*_*M-- 6 r dataframe dplyr purrr
我有一个数据框 ( df1
) 和一个数据框列表 ( test
) ,如下所示;我想加入df1
每个数据帧test
并填充一个新列 ( X
),同时保持所有其他记录完好无损。
read.table(text = "Fruits A B C D
Apple 10 1.3 NA NA
Orange 0.2 NA 0.21 NA
Grape NA 0.06 51 0.7
Grape NA 0.06 51 0.7
Grape 1 0.06 51 0.7
Grape NA 0.06 NA 0.8
Berry 11 20 0.3 0.04
Apple NA 1.1 0.5 NA
Apple NA 1.2 0.5 NA
Apple NA 1.3 0.1 NA
Berry NA NA 0.3 0.04
Berry 1 NA 0.9 0.01
Apple 1 1.3 0.5 NA
Apple 1 1.3 0.5 NA",
stringsAsFactors = FALSE, header = TRUE) -> df1
list(data.frame(Fruits = c("Apple"), A = 10, X = "oh"),
data.frame(Fruits = c("Berry"), A = 11, B = 20, X = "duh")) -> test
Run Code Online (Sandbox Code Playgroud)
这是预期的输出:
Fruits A B C D X
1 Apple 10.0 1.30 NA NA oh
2 Orange 0.2 NA 0.21 NA NA
3 Grape NA 0.06 51.00 0.70 NA
4 Grape NA 0.06 51.00 0.70 NA
5 Grape 1.0 0.06 51.00 0.70 NA
6 Grape NA 0.06 NA 0.80 NA
7 Berry 11.0 20.00 0.30 0.04 duh
8 Apple NA 1.10 0.50 NA NA
9 Apple NA 1.20 0.50 NA NA
10 Apple NA 1.30 0.10 NA NA
11 Berry NA NA 0.30 0.04 NA
12 Berry 1.0 NA 0.90 0.01 NA
13 Apple 1.0 1.30 0.50 NA NA
14 Apple 1.0 1.30 0.50 NA NA
Run Code Online (Sandbox Code Playgroud)
简单地循环遍历其中的数据帧test
是行不通的,因为它会为每个数据帧创建一个数据帧..._join
,并且还会为第二次迭代创建重复的行。也许我们可以使用条件mutate
。
purrr::map(test, ~full_join(df1, .x))
Run Code Online (Sandbox Code Playgroud)
我很可能错过了一些简单的东西,但我不想加入full_join
之后的输出,因为我的实际行df1
数超过 100 万行。
我会用purrr::reduce()
而不是map()
. 但这提出了一个问题,即在第一次迭代后,X
出现在两个数据框中并被视为键。一种解决方法是为所有X
列指定唯一的名称,然后在加入后合并。
library(dplyr)
library(purrr)
test2 <- imap(test, ~ rename(.x, "X{.y}" := X))
test2 %>%
reduce(full_join, .init = df1) %>%
mutate(X = coalesce(X1, X2), .keep = "unused")
Run Code Online (Sandbox Code Playgroud)
Fruits A B C D X
1 Apple 10.0 1.30 NA NA oh
2 Orange 0.2 NA 0.21 NA <NA>
3 Grape NA 0.06 51.00 0.70 <NA>
4 Grape NA 0.06 51.00 0.70 <NA>
5 Grape 1.0 0.06 51.00 0.70 <NA>
6 Grape NA 0.06 NA 0.80 <NA>
7 Berry 11.0 20.00 0.30 0.04 duh
8 Apple NA 1.10 0.50 NA <NA>
9 Apple NA 1.20 0.50 NA <NA>
10 Apple NA 1.30 0.10 NA <NA>
11 Berry NA NA 0.30 0.04 <NA>
12 Berry 1.0 NA 0.90 0.01 <NA>
13 Apple 1.0 1.30 0.50 NA <NA>
14 Apple 1.0 1.30 0.50 NA <NA>
Run Code Online (Sandbox Code Playgroud)
如果test
有很多元素,列出来会很烦人coalesce(X1, X2, X3, ..., Xn)
。在这种情况下,您可以使用以下替代方案:
test2 %>%
reduce(full_join, .init = df1) %>%
mutate(X = coalesce(!!!syms(paste0("X", seq_along(test2)))), .keep = "unused")
Run Code Online (Sandbox Code Playgroud)