Как свернуть фрейм данных с дублирующимися идентификаторами и разными пропущенными значениями для каждого идентификатора, чтобы NA заменялись значениями из дублирующего идентификатора? (в R) - PullRequest
0 голосов
/ 10 января 2019

У меня есть большой фрейм данных, где каждое значение в столбце ID представляет человека. Я хочу свернуть фрейм данных, чтобы каждый идентификатор (человек) заполнял меньше строк (меньше дублированных идентификаторов), но я хочу свернуть идентификаторы только в том случае, если значения, отсутствующие в других столбцах строки с идентификатором 4 (например), заменены на отсутствующие значения формируют другую строку также с ID 4 - все используют R код

Пример кадра данных ниже.

ID <- c(1, 1, 2, 4, 4, 5)
name <- c('kate', NA, 'jim', NA, 'dan', 'lou')
gender <- c(NA, 'female', 'male', 'male', NA, 'female')

(df <- data.frame(id, name, gender))

  ID name gender
1  1 kate   <NA>
2  1 <NA> female
3  2  jim   male
4  4 <NA>   male
5  4  dan   <NA>
6  5  lou female

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

Желаемый результат:

  ID name gender
1  1 kate female
3  2  jim   male
4  4  dan   male
6  5  lou female

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

ID <- c(1, 1, 2, 4, 4, 5, 5)
name <- c('kate', NA, 'jim', NA, 'dan', 'lou', 'lou smith')
gender <- c(NA, 'female', 'male', 'male', NA, 'female', 'female')
(df2 <- data.frame(ID, name, gender))

  ID      name gender
1  1      kate   <NA>
2  1      <NA> female
3  2       jim   male
4  4      <NA>   male
5  4       dan   <NA>
6  5       lou female
7  5 lou smith female
8  5      <NA> female

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

  ID      name gender
1  1      kate female
2  2       jim   male
4  4       dan   male
5  5       lou female
6  5 lou smith female

Ответы [ 2 ]

0 голосов
/ 10 января 2019
library(dplyr)

ID <- c(1, 1, 2, 4, 4, 5, 5)
name <- c('kate', NA, 'jim', NA, 'dan', 'lou', 'lou smith')
gender <- c(NA, 'female', 'male', 'male', NA, 'female', 'female')
(df2 <- data.frame(ID, name, gender, stringsAsFactors = FALSE))


df2

df2 %>%  
  group_by(ID) %>% 
  mutate(name_max = max(name, na.rm = T), 
         gender_max = max(gender, na.rm = T)) %>% 
ungroup %>% 
mutate(name   = if_else(is.na(name), name_max, name), 
       gender = if_else(is.na(gender), gender_max, gender))   %>% 
  select(ID, name, gender) %>%  
  distinct %>%  
  head(10)

слегка отредактировано:

df2 %>%  
  group_by(ID) %>% 
  mutate(name_max = max(as.character(name), na.rm = T), 
         gender_max = max(as.character(gender), na.rm = T)) %>% 
  ungroup %>% 
  mutate(name   = if_else(is.na(name), name_max, as.character(name)), 
         gender = if_else(is.na(gender), gender_max, 
as.character(gender)))   %>% 
  select(ID, name, gender) %>%  
  distinct()
0 голосов
/ 10 января 2019

Если мы заменим NA на соседнюю не-NA и получим строки distinct, а затем tidyverse, используйте fill

library(tidyverse)
df2 %>% 
   group_by(ID) %>% 
   fill(name, gender) %>% 
   fill(name, gender, .direction = 'up') %>%
   distinct
# A tibble: 5 x 3
# Groups:   ID [4]
#     ID name      gender
#  <int> <chr>     <chr> 
#1     1 kate      female
#2     2 jim       male  
#3     4 dan       male  
#4     5 lou       female
#5     5 lou smith female

данные

df2 <- structure(list(ID = c(1L, 1L, 2L, 4L, 4L, 5L, 5L, 5L), name = c("kate", 
NA, "jim", NA, "dan", "lou", "lou smith", NA), gender = c(NA, 
"female", "male", "male", NA, "female", "female", "female")),
  class = "data.frame", row.names = c("1", 
 "2", "3", "4", "5", "6", "7", "8"))
...