根据通用 id 绑定行

Binding rows based on common id

我有一个非常简单的案例,我想根据特定数据框的公共 id 元素将多个数据框组合成一个。

示例:

id <- c(1, 2, 3)
x <- c(10, 12, 14)

data1 <- data.frame(id, x)
  
id <- c(2, 3)
x <- c(20, 22)

data2 <- data.frame(id, x)

id <- c(1, 3)
x <- c(30, 32)

data3 <- data.frame(id, x)

这给了我们,

$data1
  id  x
1  1 10
2  2 12
3  3 14

$data2
  id  x
1  2 20
2  3 22

$data3
  id  x
1  1 30
2  3 32

现在,我想根据 data3 的 ID 组合所有三个数据框。预期的输出应该像

> comb
  id  x
1  1 10
2  1 NA
3  1 30
4  3 14
5  3 22
6  3 32

我正在尝试以下操作,但没有得到预期的输出。

library(dplyr)
library(tidyr)
combined <- bind_rows(data1, data2, data3, .id = "id") %>% arrange(id)

知道如何获得预期的输出吗?

bind_rows(data1, data2, data3, .id = 'grp')%>%
  complete(id, grp)%>%
  select(-grp) %>%
  filter(id%in%data3$id) 

# A tibble: 6 x 2
     id     x
  <dbl> <dbl>
1     1    10
2     1    NA
3     1    30
4     3    14
5     3    22
6     3    32

这个有用吗:

library(dplyr)
library(tidyr)
data1 %>% full_join(data2, by = 'id') %>% full_join(data3, by = 'id') %>% arrange(id) %>% right_join(data3, by = 'id') %>% 
   pivot_longer(cols = -id) %>% select(-name) %>% distinct()
# A tibble: 6 x 2
     id value
  <dbl> <dbl>
1     1    10
2     1    NA
3     1    30
4     3    14
5     3    22
6     3    32

将 3 个数据帧合并到一个列表中,并仅使用 filter 到 select 第三个数据帧中的 id

library(dplyr)
library(tidyr)

bind_rows(data1, data2, data3, .id = "new_id") %>%
  filter(id %in% id[new_id == 3]) %>%
  complete(new_id, id)

#  new_id    id     x
#  <chr>  <dbl> <dbl>
#1 1          1    10
#2 1          3    14
#3 2          1    NA
#4 2          3    22
#5 3          1    30
#6 3          3    32

一个纯基础的R解决方案也可以做到

lst <- list(data1, data2, data3)
reshape(
  subset(
    reshape(
      do.call(rbind, Map(cbind, lst, grp = seq_along(lst))),
      idvar = "id",
      timevar = "grp",
      direction = "wide"
    ),
    id %in% lst[[3]]$id
  ),
  idvar = "id",
  varying = -1,
  direction = "long"
)[c("id", "x")]

这给出了

    id  x
1.1  1 10
3.1  3 14
1.2  1 NA
3.2  3 22
1.3  1 30
3.3  3 32
> 

使用base R

do.call(rbind, unname(lapply(mget(ls(pattern = "^data\d+$")), \(x) {
        x1 <- subset(x, id %in% data3$id)
        v1 <- setdiff(data3$id, x1$id)
        if(length(v1) > 0) rbind(x1, cbind(id = v1, x = NA)) else x1
    })))

-输出

    id  x
1   1 10
3   3 14
2   3 22
11  1 NA
12  1 30
21  3 32