Замените NA значением группы в l oop в нескольких столбцах - PullRequest
1 голос
/ 24 марта 2020

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

Пример данные:

ID <- c(1,1,1,2,2,2,3,3)
V1 <- c(NA,"HEJ",NA,"BOS","BOS",NA,"IB","IB")
V2 <- c(700,700,NA,3000,NA,NA,NA,1000)
V3 <- c(NA,NA,3,1,1,1,2,NA)
V4 <- c(NA,NA,NA,NA,NA,"LA",NA,"FE")
mydf <- data.frame(ID,V1,V2,V3,V4)

> mydf
  ID   V1   V2 V3   V4
1  1 <NA>  700 NA <NA>
2  1  HEJ  700 NA <NA>
3  1 <NA>   NA  3 <NA>
4  2  BOS 3000  1 <NA>
5  2  BOS   NA  1 <NA>
6  2 <NA>   NA  1   LA
7  3   IB   NA  2 <NA>
8  3   IB 1000 NA   FE

Итак, я знаю, что если бы я хотел сделать это только для одного столбца, я бы:

setDT(mydf)[, V1:= 
                V1[!is.na(V1)][1L],
                by = ID]

И затем получил бы:

> mydf
   ID  V1   V2 V3   V4
1:  1 HEJ  700 NA <NA>
2:  1 HEJ  700 NA <NA>
3:  1 HEJ   NA  3 <NA>
4:  2 BOS 3000  1 <NA>
5:  2 BOS   NA  1 <NA>
6:  2 BOS   NA  1   LA
7:  3  IB   NA  2 <NA>
8:  3  IB 1000 NA   FE

Но У меня много столбцов, поэтому мне нужно поместить их в al oop какого-то вида.

Желаемый вывод:

> mydf
   ID  V1   V2 V3   V4
1:  1 HEJ  700  3 <NA>
2:  1 HEJ  700  3 <NA>
3:  1 HEJ  700  3 <NA>
4:  2 BOS 3000  1   LA
5:  2 BOS 3000  1   LA
6:  2 BOS 3000  1   LA
7:  3  IB 1000  2   FE
8:  3  IB 1000  2   FE

И вот что я попробовал без удачи:

names <- colnames(mydf[,-c(1)])

for(j in seq_along(nm1)){

   set(mydf,
       i = which(is.na(mydf[[names[j]]])),
       j = names[j],
       value = mydf[[names[j]]][is.na(mydf[[names[j]]])])
}

И я тоже попробовал это:

mydf[,-c(1] <- lapply(mydf, function(x) 
  replace(x, is.na(x), x[!is.na(x)]))

> mydf
  ID V1  V2   V3 V4
1  1  1 HEJ  700  3
2  1  1 HEJ  700  1
3  1  1 BOS  700  3
4  2  2 BOS 3000  1
5  2  2 BOS  700  1
6  2  2 BOS 3000  1
7  3  3  IB 1000  2
8  3  3  IB 1000  1

Извините, если я задаю вопрос, который уже существует, но я не смог его найти. Я надеюсь, что кто-нибудь может помочь мне очистить мои грязные данные:)

Ответы [ 3 ]

1 голос
/ 24 марта 2020

Мы можем использовать .SDcols, чтобы применить функцию к нескольким столбцам.

library(data.table)

cols <- names(mydf[-1])
setDT(mydf)

mydf[, (cols):= lapply(.SD, function(x) 
         replace(x, is.na(x), x[!is.na(x)][1])),.SDcols = cols, by = ID]
mydf

#   ID  V1   V2 V3   V4
#1:  1 HEJ  700  3 <NA>
#2:  1 HEJ  700  3 <NA>
#3:  1 HEJ  700  3 <NA>
#4:  2 BOS 3000  1   LA
#5:  2 BOS 3000  1   LA
#6:  2 BOS 3000  1   LA
#7:  3  IB 1000  2   FE
#8:  3  IB 1000  2   FE
1 голос
/ 24 марта 2020

Один dplyr и tidyr могут быть:

mydf %>%
 group_by(ID) %>%
 fill(-ID, .direction = "downup")

     ID V1       V2    V3 V4   
  <dbl> <fct> <dbl> <dbl> <fct>
1     1 HEJ     700     3 <NA> 
2     1 HEJ     700     3 <NA> 
3     1 HEJ     700     3 <NA> 
4     2 BOS    3000     1 LA   
5     2 BOS    3000     1 LA   
6     2 BOS    3000     1 LA   
7     3 IB     1000     2 FE   
8     3 IB     1000     2 FE 
0 голосов
/ 24 марта 2020

Мы можем использовать na.locf от zoo

library(data.table)
setDT(df1)[, na.locf(.SD), by = ID, .SDcols = V2:V4]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...