Заполнение значений на панели данных


У меня есть данные панели, содержащие значения NA. Я хотел бы заполнить NAs значениями других данных. Допустим, я хочу завершить следующее panel с помощью new.df.

panel <- data.frame("time" = c(rep(2000,5), rep(2001,5)), 
                    "var1" = rep(1:5, times=2), 
                    "var2" = c(NA,'b','c',NA,'d','a1','b1','c1',NA,'d1'))

new.df <- data.frame("time" = c(2000:2001), 
                     "var1" = c(4,4), 
                     "var2" = c('e','e'))

Я попробовал другую комбинацию merge / aggregate / ddplyr и т. д.. Проблема в том, что merge или merge.data.frame создает дополнительные столбцы, индексируемые .x и .y, даже если имена столбцов идентичны.

> merge(panel,new.df,by = c("time","var1"), all=T)
   time var1 var2.x var2.y
1  2000    1   <NA>   <NA>
2  2000    2      b   <NA>
3  2000    3      c   <NA>
4  2000    4   <NA>      e
5  2000    5      d   <NA>
6  2001    1     a1   <NA>
7  2001    2     b1   <NA>
8  2001    3     c1   <NA>
9  2001    4   <NA>      e
10 2001    5     d1   <NA>

Я также пытался играть с опцией na.action без успеха, потому что панель все равно будет неполные после слияния и оставшиеся NA должны оставаться такими, как они есть. (В зависимости от формулировки, обработка NA в некоторых случаях заменит NA на 0, или на NaN)

Я хотел бы найти способ нацелить правильные индексы в панели, чтобы "вставить" new.df$var2 в нужное место, зная, что у меня есть очень большая панель, и она останется неполной в конце.

Заранее благодарю.

3 2

3 ответа:

Мы можем использовать coalesce из tidyr

library(tidyr)
library(dplyr)
full_join(as.data.frame(panel),as.data.frame(new.df),by = c("time","var1")) %>% 
       mutate_each(funs(as.character), var2.x:var2.y) %>%
       mutate(var2= coalesce(var2.x, var2.y)) %>% 
       select(-var2.x, -var2.y)
#   time var1 var2
#1  2000    1 <NA>
#2  2000    2    b
#3  2000    3    c
#4  2000    4    e
#5  2000    5    d
#6  2001    1   a1
#7  2001    2   b1
#8  2001    3   c1
#9  2001    4    e
#10 2001    5   d1

Или мы можем использовать опцию base R с max.col. Здесь ' d1 ' - это выход ОП с merge

 d1$var2 <-d1[,3:4][cbind(1:nrow(d1), max.col(!is.na(d1[3:4]), "first"))]
 d1$var
 #[1] NA   "b"  "c"  "e"  "d"  "a1" "b1" "c1" "e"  "d1"

Или просто (предполагая, что все значения в новом.ДФ карте на соответствующее значение на панели):

ind <- which(paste0(panel[,1],panel[,2]) %in% paste0(new.df[,1],new.df[,2]))
panel[ind,3] = new.df[,3]

Воссоздать данные в виде фрейма данных

library(dplyr)
panel <- data_frame("time" = c(rep(2000,5), rep(2001,5)), 
                    "var1" = rep(1:5, times=2), 
                    "var2" = c(NA,'b','c',NA,'d','a1','b1','c1',NA,'d1'))

new.df <- data_frame("time" = c(2000:2001), 
                     "var1" = c(4,4), 
                     "var2" = c('e','e'))

Решение 1 Заполните значения NA основанием R merge

panelnew <- merge(panel,new.df,by = c("time","var1"), all=T)
panelnew$var2 <- ifelse(is.na(panelnew$var2.x), panelnew$var2.y, panelnew$var2.x)
panelnew[c("time","var1","var2")]
   time var1 var2
1  2000    1 <NA>
2  2000    2    b
3  2000    3    c
4  2000    4    e
5  2000    5    d
6  2001    1   a1
7  2001    2   b1
8  2001    3   c1
9  2001    4    e
10 2001    5   d1

Решение 2 Заполните значения NA dplyr left_join и мутируйте

Здесь я использую dplyr left_join, чтобы присоединить новые значения. Используйте full_join, Если вы хотите также добавить комбинации time и var1, которых не было в исходной панели. Вы получите столбцы var2.x и var2.y, и это нормально, потому что это отражает тот факт, что есть старое и новое значение. Затем мутировать, чтобы заменить NA значения по новому значению.

result <- panel %>% 
    left_join(new.df, by = c("time", "var1")) %>% 
    mutate(var2 = ifelse(is.na(var2.x),var2.y,var2.x))

Тогда, если вы хотите сохранить только интересующие столбцы

result <- result %>% select(time, var1, var2)

Что вы планируете делать, если новое значение заменяет существующее значение? Приведенный выше код сохранит старое значение.