如何使用dplyr从基于另一个数据帧的数据帧填充列

时间:2018-09-27 04:25:22

标签: r dplyr

我有两个数据帧,我试图使用第一个数据帧的列中的值替换第二个数据帧的列中的NA。我想使用dplyr软件包来做到这一点,但我对此软件包并不熟悉:

以下是可重现的示例:

library(dplyr)
## Create the two data frames
      dt1 <- data.frame(ID = c(rep(1, 6), rep(2, 6), rep(3, 6)), day = c(seq(0, 5, by= 1), seq(0, 5, by= 1), seq(0, 5, by= 1)), density = sample(1:100, 6*3))
      dt2 <- data.frame(ID = c(rep(1, 6), rep(2, 6), rep(3, 6)), day = c(seq(0, 5, by= 1), seq(0, 5, by= 1), seq(0, 5, by= 1)), density = NA)

## Fill the second data frame
     dt2[dt2$day == 0, c("density")] <- c(1, 2, 8)
     dt2[dt2$day %in% c(1, 2, 3, 4, 5), c("density")] <- dt1[dt1$day %in% c(0, 1, 2, 3, 4), c("density")] 
## the values in the column "ID" of dt1 must be equivalent to the values in the column "ID" of dt2

如何使用dplyr包重现最后两个命令?

这是我的考试:

  dt2_fill <- dt2 %>% 
    mutate(density = if(day == 0){c(1, 2, 8)},
           density = if(day %in% c(1, 2, 3, 4, 5)){dt1[dt1$day %in% c(0, 1, 2, 3, 4), c("density")]})

但是此代码不起作用。

2 个答案:

答案 0 :(得分:2)

这可能不是理想的解决方案,但可以提供预期的输出

完整的dplyr解决方案

library(dplyr)
dt2 %>%
  filter(day == 0) %>%
  mutate(density = c(1, 2, 8)) %>%
  bind_rows(dt2 %>%
              filter(day %in% c(1, 2, 3, 4, 5)) %>%
              mutate(density = dt1 %>%
                              filter(day %in% c(0, 1, 2, 3, 4)) %>% 
                               pull(density)
             ))

#   ID day density
#1   1   0       1
#2   2   0       2
#3   3   0       8
#4   1   1      84
#5   1   2      72
#6   1   3       4
#7   1   4      31
#....

我们首先为filter day == 0行,并为其分配值c(1, 2, 8)。对于其余的行,我们从density中获得相应的dt1列。


我们可以通过以下方式降低复杂性

dt2 %>%
   filter(day == 0) %>%
   mutate(density = c(1, 2, 8)) %>%
   bind_rows(dt2 %>%
              filter(day %in% c(1, 2, 3, 4, 5)) %>%
              mutate(density = dt1$density[dt1$day %in% c(0, 1, 2, 3, 4)])
          )

答案 1 :(得分:2)

您似乎在这里尝试做的事情,至少在实践中,是合并两个数据帧。您的IDday变量用作唯一标识符,除了dt1中的day变量在dt2中偏移了一个。那么这样的解决方案呢?

dt2 <- dt1 %>% 
  mutate(day = day + 1) %>% # Adjust "day" variable to line up with the "day" variable in dt2
  right_join(dt2 %>% select(-density), by = c("ID", "day"))

day == 0的情况下,NA将保留在密度变量中。您可以使用Ronak上面建议的过滤器/绑定行解决方案解决该问题,也可以使用ifelse语句来分配这些情况,如下所示:

dt2 <- dt2 %>% 
  mutate(density = ifelse(day > 0, density,
                          ifelse(ID == 1, 1,
                                 ifelse(ID == 2, 2, 8))))

(这有点麻烦,我想如果您想提供更多详细信息,在您的实际案例中可能会有更好的解决方案。)

另一种选择就是直接从dt1创建dt2数据帧:

dt2 <- dt1 %>% 
  mutate(day = day + 1) %>% 
  filter(day < 6) %>% 
  bind_rows(tibble(ID = c(1,2,3), day = 0, density = c(1,2,8))) %>% 
  arrange(ID, day)