Как заполнить NA разных столбцов, сгруппированных по дублированным идентификаторам в R - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть таблица со столбцами id, colA и colB.Данные содержат дублированные столбцы идентификаторов, где для некоторых строк colA или colB имеет значение NULL, но их дублированный id имеет допустимые значения.Я хочу очистить данные, чтобы удалить дубликаты, но у меня есть полные данные.Например, мои данные выглядят как

id | colA | colB
 1     NA    X
 1      Y    X
 2      Z    NA
 2      Z    Y
 3      Z    Y
 3      Z    Y
 4     NA    NA
 4     NA    NA

, и я хочу, чтобы мой фрейм данных выглядел как

id | colA | colB
1     Y      X
2     Z      Y
3     Z      Y
4     NA     NA

Я обычно использую оператор ifelse для замены пропущенных значений, но я запутался вкак использовать это в контексте дублирования id s.

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Сначала добавьте столбец, который сообщает, сколько NA с в каждой строке.Затем, используя dplyr, сначала удалите дублирующиеся строки, а затем для каждого идентификатора сохраняйте строку с наименьшим отсутствующим значением -

df$test <- rowSums(is.na(df))

df %>% 
  filter(!duplicated(.)) %>% 
  arrange(id, test) %>% 
  group_by(id) %>% 
  filter(row_number() == 1) %>% 
  ungroup() %>% 
  select(-test)

# A tibble: 4 x 3
     id colA  colB 
  <int> <chr> <chr>
1     1 y     x    
2     2 z     y    
3     3 z     y    
4     4 <NA>  <NA> 

РЕДАКТИРОВАТЬ: На самом деле нет необходимости удалять дубликаты в первую очередь.Простое сохранение строки с наименьшим количеством пропущенных значений для каждого идентификатора также должно работать -

df$test <- rowSums(is.na(df))

df %>% 
  arrange(id, test) %>% 
  group_by(id) %>% 
  filter(row_number() == 1) %>% 
  ungroup() %>% 
  select(-test)

Данные -

df <- data.frame(
  id = c(rep(seq(1:4), each =2)), colA = c(NA, "y", "z", "z", "z", "z", NA, NA), 
  colB = c("x", "x", NA, "y", "y", "y", NA, NA), stringsAsFactors = F)
0 голосов
/ 20 ноября 2018

Этот ответ очень зависит от того, что ваши фактические данные похожи по структуре на данные вашего примера.

Ваши данные:

df1 <- structure(list(id = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L), 
                      colA = c(NA, "Y", "Z", "Z", "Z", "Z", NA, NA), 
                      colB = c("X", "X", NA, "Y", "Y", "Y", NA, NA)), 
                      class = "data.frame", 
                      row.names = c(NA, -8L))

Предполагая, как в вашем примере, что каждый id встречается дважды и что, когда одно наблюдение равно NA, это первое наблюдение для этого id, тогда это работает:

library(dplyr)
library(tidyr)

df1 %>% 
  group_by(id) %>% 
  fill(colA, colB, .direction = "up") %>%  
  ungroup() %>% 
  distinct()

# A tibble: 4 x 3
     id colA  colB 
  <int> <chr> <chr>
1     1 Y     X    
2     2 Z     Y    
3     3 Z     Y    
4     4 NA    NA 

Если второе наблюдение для id может быть NA, вы можете попробовать добавить секунду fill после первого, но на этот раз заполните:

df1 %>% 
  group_by(id) %>% 
  fill(colA, colB, .direction = "up") %>%  
  fill(colA, colB, .direction = "down") %>%  
  ungroup() %>% 
  distinct()
0 голосов
/ 20 ноября 2018

Создание фрейма данных - это помогает, если вы публикуете код для создания примера данных

df <- data.frame(id = c(rep(seq(1:4), each =2)), colA = c(NA, "y", "z", "z", "z", "z", NA, NA), colB = c("x", "x", NA, "y", "y", "y", NA, NA))

Удаление строк с одиночными NA

for(i in 1:nrow(df)){

  if(is.na(df[i,]$colA) & !is.na(df[i,]$colB) | !is.na(df[i,]$colA) & is.na(df[i,]$colB)){

df <- df[-i,]

  }
}

Удаление оставшихся дубликатов (т. Е. Двойных строк NA)

df  <- df[!duplicated(df), ]

Вывод

df

Возможно, это более эффективный в вычислительном отношении способ, но это должно сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...