Заполнение НА значениями соседних ячеек в R - PullRequest
1 голос
/ 27 мая 2020

Этот вопрос может показаться похожим на другие вопросы на этом форуме, и прежде чем пометить его как дублирующийся, убедитесь, что дубликат работает в моем случае.

У меня есть фрейм данных ( df1 ), как показано ниже:

> df1 <- data.frame(c1=c('ER017','ER017','ER017','ER017','ER017','ER018','ER018','ER018','ER018'),c2=c(1,4,3,2,5,3,1,2,4),c3=c(18,NA,20,NA,NA,150,NA,NA,200))
> df1

 c1        c2       c3
-----------------------
ER017       1       18
ER017       4       NA
ER017       3       20
ER017       2       NA
ER017       5       NA
ER018       3      150
ER018       1       NA
ER018       2       NA
ER018       4      200

Я хотел бы заменить NA в c3 таким образом, чтобы значение было из предыдущей ячейки на основе от значений c1 и c2. Например, для ER017; c2 = 1, c3 = 18, поэтому для ER017; c2 = 2, c3 было бы 18, если бы не ER017; c2 = 4, c3 будет 20, поскольку значение изменяется для ER017 и c2 = 3, что является предыдущей ячейкой. Аналогично, для ER018, c2 = 1 и c2 = 2, c3 должно иметь 150, поскольку для c2 = 3 соответствует c3 = 150.

Ниже приведен желаемый результат:

 c1        c2       c3
-----------------------
ER017       1       18
ER017       2       18
ER017       3       20
ER017       4       20
ER017       5       20
ER018       1      150
ER018       2      150
ER018       3      150
ER018       4      200

Я пробовал следующие фрагменты кода, но результат неверен.

> library(zoo)
> library(dplyr)

> df1 %>% arrange(c1,c2) %>% group_by(c1,c2) %>% mutate(c3 = na.locf0(c3)) %>% ungroup


c1       c2    c3
-------------------
ER017     1    18
ER017     2    18
ER017     3    20
ER017     4    20
ER017     5    20
ER018     1    20
ER018     2    20
ER018     3   150
ER018     4   200
> df1 %>% arrange(c1, c2) %>% fill(c3) %>% fill(c3, .direction = "up")

c1    c2   c3
--------------
ER017  1   18
ER017  2   18
ER017  3   20
ER017  4   20
ER017  5   20
ER018  1   20
ER018  2   20
ER018  3  150
ER018  4  200

Ни один из эти решения работают в моем случае, как и для ER018, c2 = 1 и 2, c3 должно быть 150, но каким-то образом значение 20 переносится с ER017 на ER018. Может ли кто-нибудь помочь в получении желаемого результата, как указано выше?

Ответы [ 3 ]

5 голосов
/ 27 мая 2020

Вам нужно установить .direction = "downup" в fill(), чтобы заполнить пропущенные значения сначала вниз, а затем вверх.

df1 %>%
  group_by(c1) %>%
  arrange(c2, .by_group = T) %>%
  fill(c3, .direction = "downup") %>%
  ungroup()

# # A tibble: 9 x 3
#   c1       c2    c3
#   <fct> <dbl> <dbl>
# 1 ER017     1    18
# 2 ER017     2    18
# 3 ER017     3    20
# 4 ER017     4    20
# 5 ER017     5    20
# 6 ER018     1   150
# 7 ER018     2   150
# 8 ER018     3   150
# 9 ER018     4   200
3 голосов
/ 27 мая 2020

Аналогично использованию решения Даррена, но с использованием nafill из data.table

library(data.table)
setDT(df1)
df1[order(c2), nafill(nafill(c3, type = 'locf'), type = 'nocb'), by = c1]
2 голосов
/ 27 мая 2020

Раствор Base R:

data.frame(do.call("rbind", lapply(split(df1, df1$c1), function(x){
      x <- x[order(x$c2),]
      x$c3[1] <- ifelse(is.na(x$c3[1]), x$c3[which(!(is.na(x$c3)))[1]], x$c3[1])
      x$c3 <- na.omit(x$c3)[cumsum(!(is.na(x$c3)))]
      return(x)
    }
  )
), row.names = NULL)
...