изменить форму данных с отсутствующими значениями в Tidyr - PullRequest
1 голос
/ 27 марта 2019

У меня есть датафрейм вроде:

library(tidyverse) 

df_mess <- tibble::tribble(
  ~id, ~value, ~answer_text,
  123,     25,        "age",
  123,     NA,     "female",
  234,     29,        "age",
  234,     NA,       "male",
  345,     14,        "age",
  345,     NA,     "female"
  )

Я бы хотел изменить форму, чтобы получить «аккуратные» данные, то есть по 1 строке для каждого наблюдения.

df <- tibble::tribble(
  ~id, ~age,     ~sex,
  123,   25, "female",
  234,   29,   "male",
  345,   14, "female"
  )

Я попробовал версию gather / spread, но мне не повезло.

Любое руководство ценится.

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

Вот решение с распространением и сбором.spread получит все переменные, такие как age, где имя переменной появляется в столбце answer_text.Если значения переменной находятся в столбце answer_text (как, например, sex), вам нужно gather вернуть их обратно, как показано ниже.

Чтобы заставить работать столбец sex, я изменилNAs в value до -99.Вы можете использовать любое значение, хотя.Если вы распространили без чего-либо в столбце value, он будет отображаться как NA в столбцах female и male, созданных из разворота.

df_mess[is.na(df_mess)] <- -99

df_mess %>% 
  spread(answer_text, value) %>% 
  gather(sex, temp, female, male, na.rm = TRUE) %>% 
  select(-temp)

output

# A tibble: 3 x 3
     id   age sex   
  <dbl> <dbl> <chr> 
1   123    25 female
2   345    14 female
3   234    29 male 

Пример с большим количеством переменных и допустимым NA в переменной size для id 123.

   df_mess <- tibble::tribble(
  ~id, ~value, ~answer_text,
  123,     25,        "age",
  123,     NA,     "female",
  234,     29,        "age",
  234,     NA,       "male",
  345,     14,        "age",
  345,     NA,     "female",
  123,     NA,      "brown",
  234,     NA,     "blonde",
  345,     NA,      "black",
  123,     NA,       "size",
  234,     30,       "size",
  345,     40,       "size",

)
df_mess[is.na(df_mess)] <- -99
df_clean <- df_mess %>% 
  spread(answer_text, value) %>% 
  gather(sex, temp, female, male, na.rm = TRUE) %>% 
  select(-temp) %>% 
  gather(hair, temp, black:brown, na.rm = TRUE) %>% 
  select(-temp)

df_clean[df_clean == -99] <- NA
df_clean

output

     id   age  size sex    hair  
  <dbl> <dbl> <dbl> <chr>  <chr> 
1   345    14    40 female black 
2   234    29    30 male   blonde
3   123    25    NA female brown
0 голосов
/ 27 марта 2019

Если структура ваших данных всегда одинакова, я бы сделал что-то вроде:

df_mess$new <- lead(df_mess$answer_text)
df_mess <- subset(df_mess,df_mess$value>0)

, но это возможное решение только для этого конкретного случая.

...