将 Dataframe 与存储在具有不同列的列表中的多个 Dataframe 连接

anauzrmj  于 2023-02-10  发布在  其他
关注(0)|答案(3)|浏览(128)

我有一个 Dataframe (df1)和一个 Dataframe 列表(test),如下所示;我想将df1test中的每个 Dataframe 连接起来,并填充一个新列(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

下面是预期输出:

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

简单地在test中循环 Dataframe 是不起作用的,因为它为每个..._join创建了一个 Dataframe ,也为第二次迭代创建了重复的行。

purrr::map(test, ~full_join(df1, .x))

很可能我遗漏了一些简单的内容,但我不想在后面连接full_join的输出,因为实际的df1有超过1M行。

iyfamqjs

iyfamqjs1#

看起来这可能是新的rows_update()方法的一个很好的用法。您可以在reduce中迭代要更新的行列表,以便按顺序应用它们。

purrr::reduce(test, function(data, match) {
  rows_update(data, match, setdiff(names(match), "X"))
}, .init=data.frame(df1, X=NA_character_))

这会添加一个名为X的列,该列一开始都是NA,然后在每次迭代时,它会使用不名为“X”的任何重叠列来更新X的值。

33qvvth1

33qvvth12#

我会使用purrr::reduce()而不是map(),但这会带来一个问题,即在第一次迭代后,X会出现在两个 Dataframe 中,并被视为键。一个解决方法是为所有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")
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>

如果test有很多元素,列出coalesce(X1, X2, X3, ..., Xn)会很麻烦,在这种情况下,可以使用以下替代方法:

test2 %>% 
  reduce(full_join, .init = df1) %>% 
  mutate(X = coalesce(!!!syms(paste0("X", seq_along(test2)))), .keep = "unused")
6ju8rftf

6ju8rftf3#

我们可以用

library(powerjoin)
library(dplyr)
test %>% 
   reduce(power_full_join, .init = df1, conflict = coalesce_xy)

相关问题