Уборка в R: как свернуть мои двоичные столбцы в символы на основе векторов? - PullRequest
0 голосов
/ 01 мая 2019

Я убираю свои данные в R и хочу превратить несколько столбцов в 1, используя функцию, перебирающую элементы вектора. Мне было интересно, можете ли вы помочь мне:

  • отработать семантическую ошибку,
  • и сделать мой код более эффективным?

Мои данные основаны на опросе с 32 вопросами. На каждый вопрос есть несколько ответов. Каждый ответ представляет собой столбец с вариантами 1 и NA.

Для одного вопроса часть набора данных может быть воспроизведена следующим образом:

XV2_1 <- c(1,NA,NA,NA)
XV2_2 <- c(NA,1,NA,NA)
XV2_3 <- c(NA,NA,NA,1)
XV2_4 <- c(NA,NA,1,NA)
id <- c(12,13,14,15)

dat <- data.frame(id,XV2_1, XV2_2, XV2_3,XV2_4)

> dat
  id XV2_1 XV2_2 XV2_3 XV2_4
1 12     1    NA    NA    NA
2 13    NA     1    NA    NA
3 14    NA    NA    NA     1
4 15    NA    NA     1    NA

Это данные, которые я хотел бы получить (

question_2_answers <- c("Yellow","Blue","Green","Orange") #this is a vector based on the answers of the questionnaire

collapsed <- c("Yellow","Blue","Orange","Green")

collapsed_dataframe <- data.frame(id,collapsed)
>collapsed_dataframe
  id   X2
1 12   Yellow
2 13   Blue
3 14   Green
4 15   Orange

До сих пор я пробовал последовательность "ifelse's" в сочетании с mutate:

library(tidyverse)
question_2_answers <- c("Yellow","Blue","Green","Orange") #this is a vector based on the answers of the questionnaire

dat %>%
  mutate(
    Colour = tidy_Q2(question_2_answers,XV2_1,XV2_2,XV2_3,XV2_4)
  )

tidy_Q2 <- function(a,b,c,d,e) {
  ifelse(b == 1, a[1],ifelse(
    c==1,a[2],ifelse(
      d==1,a[3],a[4])))
}

Однако мой вывод не такой, как ожидалось:

  id XV2_1 XV2_2 XV2_3 XV2_4 Colour
1 12     1    NA    NA    NA Yellow
2 13    NA     1    NA    NA   <NA>
3 14    NA    NA    NA     1   <NA>
4 15    NA    NA     1    NA   <NA>

Мне бы хотелось, чтобы это было так:

  id XV2_1 XV2_2 XV2_3 XV2_4 Colour
1 12     1    NA    NA    NA Yellow
2 13    NA     1    NA    NA   Blue
3 14    NA    NA    NA     1   Green
4 15    NA    NA     1    NA   Orange

Кто-нибудь знает способ убрать ошибку? Другой вопрос, который я хотел бы задать, может ли мой код быть более эффективным? После этого у меня есть 32 опроса survey_questions, я хотел бы максимально автоматизировать процесс. Примечательные вещи, которые следует иметь в виду:

  • не все вопросы опроса имеют одинаковое количество вариантов (т.е. вопрос 2 имеет 2 варианта и, следовательно, 2 столбца, в то время как вопрос 10 имеет 8 вариантов и 8 столбцов)
  • некоторые значения являются строками, а не 1 или NA

Всегда рад учиться,

Best

Maria

Ответы [ 2 ]

2 голосов
/ 01 мая 2019

Это своего рода преобразование ширины в длину , которое мы можем сделать с помощью tidyr::gather:

Сначала мы сделаем цвета именами столбцов соответствующих строк:

# Replace column names (except for the `id` column) with color values
colnames(dat)[-1] <- c("Yellow","Blue","Orange","Green")

dat
  id Yellow Blue Orange Green
1 12      1   NA     NA    NA
2 13     NA    1     NA    NA
3 14     NA   NA     NA     1
4 15     NA   NA      1    NA

Затем мы собираем столбцы без идентификатора и удаляем значения NA:

library(tidyverse)
dat %>%
    gather(X2, val, -id) %>%   # Gather color cols from wide to long format
    filter(!is.na(val)) %>%    # Drop rows with NA values
    select(-val)               # Remove the unnecessary `val` column

  id     X2
1 12 Yellow
2 13   Blue
3 15 Orange
4 14  Green

Это будет работать с любым количеством столбцов (вам просто нужно указать все столбцы, которые вы не хочет собрать) и сохраняет строки с не NA значениями.Если вы хотите, чтобы другие условия исключали строку (например, если 0 или 'unknown' должны считаться неотвеченными, или только 'correct' считается ответом), то вы должны добавить эти условия к filterзаявление.

1 голос
/ 01 мая 2019

Один из вариантов в base R будет max.col - найти индекс столбца значений, которые не являются NA в каждой строке, используйте его, чтобы получить имена столбцов, соответствующие индексу, создайте данные из 2 столбцов. кадр cbind с первым столбцом

i1 <- max.col(!is.na(dat[-1]), 'first')
cbind(dat['id'], Colour = names(dat)[-1][i1])
#  id Colour
#1 12 Yellow
#2 13   Blue
#3 14  Green
#4 15 Orange

данные

dat <-  structure(list(id = c(12, 13, 14, 15), Yellow = c(1, NA, NA, 
NA), Blue = c(NA, 1, NA, NA), Orange = c(NA, NA, NA, 1), Green = c(NA, 
NA, 1, NA)), class = "data.frame", row.names = c(NA, -4L))
...