Разделить столбец конкатенированных данных с разделителями-запятыми и вывести их в качестве коэффициентов

Я пытаюсь очистить некоторые данные, которые были неправильно введены. Вопрос о переменной допускает множественные ответы из пяти вариантов, пронумерованных как от 1 до 5. Данные были введены следующим образом (это всего лишь пример - есть много других переменных и много других наблюдений в реальных данных кадр):

data
          V1
1    1, 2, 3
2    1, 2, 4
3 2, 3, 4, 5
4    1, 3, 4
5    1, 3, 5
6 2, 3, 4, 5

Здесь приведен код для воссоздания данных примера:

data = data.frame(V1 = c("1, 2, 3", "1, 2, 4", "2, 3, 4, 5", 
                         "1, 3, 4", "1, 3, 5", "2, 3, 4, 5"))

На самом деле мне нужны данные, которые нужно обрабатывать больше... binary - как набор вопросов "да/нет" - введен в кадр данных, который больше напоминает:

data
    V1.1  V1.2  V1.3  V1.4  V1.5
1      1     1     1    NA    NA
2      1     1    NA     1    NA
3     NA     1     1     1     1
4      1    NA     1     1    NA
5      1    NA     1    NA     1
6     NA     1     1     1     1

Фактические имена переменных не имеют значения на данный момент - я могу легко исправить это. Кроме того, не имеет большого значения, являются ли недостающие элементы "O", "NA" или "blank" - снова, что я могу исправить позже.

Я пробовал использовать функцию transform из пакета reshape, а также загружать разные вещи с помощью strsplit, но я не могу заставить делать то, что я ищу. Я также рассмотрел многие другие связанные вопросы о Stackoverflow, но они, похоже, не совсем такие же проблемы.

Ответ 1

Вам просто нужно написать функцию и использовать apply. Сначала некоторые фиктивные данные:

##Make sure you're not using factors
dd = data.frame(V1 = c("1, 2, 3", "1, 2, 4", "2, 3, 4, 5", 
                         "1, 3, 4", "1, 3, 5", "2, 3, 4, 5"), 
                     stringsAsFactors=FALSE)

Затем создайте функцию, которая принимает строку и при необходимости преобразуется

make_row = function(i, ncol=5) {
  ##Could make the default NA if needed
  m = numeric(ncol)
  v = as.numeric(strsplit(i, ",")[[1]])
  m[v] = 1
  return(m)
}

Затем используйте apply и перенесите результат

t(apply(dd, 1, make_row))

Ответ 2

Спустя долгое время я, наконец, добрался до создания пакета ( "splitstackshape" ), который имеет дело с такими типами данных в эффективном манера. Таким образом, для удобства других (и, конечно же, саморекламы) здесь существует компактное решение.

Соответствующей функцией для этой проблемы является cSplit_e.

Сначала настройки по умолчанию, которые сохраняют исходный столбец и используют NA в качестве заливки:

library(splitstackshape)
cSplit_e(data, "V1")
#           V1 V1_1 V1_2 V1_3 V1_4 V1_5
# 1    1, 2, 3    1    1    1   NA   NA
# 2    1, 2, 4    1    1   NA    1   NA
# 3 2, 3, 4, 5   NA    1    1    1    1
# 4    1, 3, 4    1   NA    1    1   NA
# 5    1, 3, 5    1   NA    1   NA    1
# 6 2, 3, 4, 5   NA    1    1    1    1

Во-вторых, с отбрасыванием исходного столбца и использованием 0 в качестве заливки.

cSplit_e(data, "V1", drop = TRUE, fill = 0)
#   V1_1 V1_2 V1_3 V1_4 V1_5
# 1    1    1    1    0    0
# 2    1    1    0    1    0
# 3    0    1    1    1    1
# 4    1    0    1    1    0
# 5    1    0    1    0    1
# 6    0    1    1    1    1