基于公共 ID 绑定行

时间:2021-06-10 06:53:14

标签: r dplyr tidyr

我有一个非常简单的案例,我想根据特定数据框的公共 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)

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

5 个答案:

答案 0 :(得分:3)

这行得通吗:

a = (dt.datetime(2021, 6, 1, 18, 0) - t_b).dt.total_seconds()

答案 1 :(得分:2)

将 3 个数据帧合并到一个列表中,并使用 filter 仅选择第三个数据帧中的 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

答案 2 :(得分:2)

纯 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
> 

答案 3 :(得分:2)

使用 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

答案 4 :(得分:1)

private static void printMode(double[][] doubles) {
    HashMap<Double , Double> map = new HashMap();

    for (int i = 0; i < doubles.length; i++) {
        for (int j = 0; j < doubles[i].length; j++) {
            double temp = doubles[i][j];
            if(map.get(temp)==null){
                map.put(doubles[i][j],1.0);
            }else {
                double temp2 = (double) map.get(temp);
                map.put(doubles[i][j],++temp2);
            }
        }
    }
    Object[] objects = map.values().stream().sorted().toArray();
    Stream stream = map.entrySet().stream().filter(val-> val.getValue().equals(objects[objects.length-1]));
    stream.forEach(System.out::println);
}