使用 `accumulate` 将列表中的数据帧反连接到原始的先前数据帧

问题描述 投票:0回答:3

我有一个数据框列表,

a
b
,和
c
。我想得到一个列表,其中
a
不会被更改,
b
将只包含那些不在
a
中的行,而
c
将只包含那些不在
b
.

中的行
# Sample data
a <- data.frame(num = 1:4, let = letters[1:4])
b <- data.frame(num = 2:6, let = letters[2:6])
c <- data.frame(num = 3:8, let = letters[3:8])

dfs <- list(a, b, c)

让我感到困惑的部分是我需要在 original 之前的数据帧上执行反连接,而不是在反连接到其之前的数据帧之后创建的数据帧。我的直觉是使用

accumulate
中的
purrr
来执行此操作,但我无法弄清楚如何让它在原始的先前数据帧上工作。

dfs |> 
  accumulate(~anti_join(.y, .x))

[[1]]
  num let
1   1   a
2   2   b
3   3   c
4   4   d

[[2]]
  num let
1   5   e
2   6   f

[[3]]
  num let
1   4   d
2   7   g
3   8   h

因为这加入了已经加入的先前数据框,所以我在第三个 df 中有

4 d
,这是我不想要的。

我已经尝试过

.dir = "backward"
作为使用原始dfs加入的一种方式,但这并没有做我认为应该做的事情:

dfs |> 
   accumulate(~anti_join(.y, .x), .dir = "backward")

[[1]]
  num let
1   7   g
2   8   h

[[2]]
  num let
1   7   g
2   8   h

[[3]]
  num let
1   4   d
2   5   e
3   6   f
4   7   g
5   8   h

有没有办法设置

accumulate
的参数,这样它就可以做到这一点,或者我需要一种不同的方法吗?如果可能的话,我更喜欢 purrr/tidyverse,但我愿意接受任何满足我需要的东西。

预期产出:

[[1]]
  num let
1   1   a
2   2   b
3   3   c
4   4   d

[[2]]
  num let
1   5   e
2   6   f

[[3]]
  num let
1   7   g
2   8   h
r dplyr purrr
3个回答
1
投票

accumulate
是为动态排序而设计的,这里你需要一个锚点,
df[[1]]
,以及一个应用于列表其余元素的函数:

dfs[-1] <- map(dfs[-1], ~ anti_join(.x, dfs[[1]]))
[[1]]
  num let
1   1   a
2   2   b
3   3   c
4   4   d

[[2]]
  num let
1   5   e
2   6   f

[[3]]
  num let
1   5   e
2   6   f
3   7   g
4   8   h

0
投票

您可以使用

map_at()
选择性地将
anti_join
应用于除第一个之外的每个 data.frame。

map_at(dfs, -1, ~ anti_join(.x, dfs[[1]]))
[[1]]
  num let
1   1   a
2   2   b
3   3   c
4   4   d

[[2]]
  num let
1   5   e
2   6   f

[[3]]
  num let
1   5   e
2   6   f
3   7   g
4   8   h

0
投票

只用

dplyr
,你可以做:

dfs %>%
 bind_rows(., .id = "df") %>%
 filter(!(duplicated(num) & duplicated(let))) %>%
 group_split(df, .keep = FALSE)

[[1]]
# A tibble: 4 × 2
    num let  
  <int> <chr>
1     1 a    
2     2 b    
3     3 c    
4     4 d    

[[2]]
# A tibble: 2 × 2
    num let  
  <int> <chr>
1     5 e    
2     6 f    

[[3]]
# A tibble: 2 × 2
    num let  
  <int> <chr>
1     7 g    
2     8 h 
© www.soinside.com 2019 - 2024. All rights reserved.