Как заполнить столбец из фрейма данных на основе другого фрейма данных с помощью dplyr - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть два фрейма данных, и я пытаюсь заменить 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 голосов
/ 27 сентября 2018

Похоже, что вы пытаетесь здесь, по крайней мере на практике, объединить два фрейма данных.Ваши переменные ID и day работают как уникальные идентификаторы, за исключением того, что переменная day в dt1 отключена на единицу в 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"))

Это оставит NA в переменной плотности для случаев, когда day == 0.Вы можете решить это, используя решение filter / bind-row, которое предлагает Ронак выше, или вы можете назначить эти случаи, используя ifelse операторы, например, так:

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

(Это немного kludge-y, иЯ подозреваю, что может быть лучшее решение в вашем случае, если вы хотите предоставить больше деталей.)

Другой вариант - просто создать ваш фрейм данных dt2 непосредственно из dt1:

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)
0 голосов
/ 27 сентября 2018

Это может быть не идеальное решение, но дает ожидаемый результат

Полное 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)])
          )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...