как работать со столбцом, содержащим несколько значений, разделенных запятыми, на языке R

В моем наборе данных (файл CSV) есть столбец, а именно удобства. Он содержит такие значения, как {"Беспроводной Интернет", "Доступ для кресел-каталок", Кухня, Лифт, "Зуммер / беспроводной домофон", Отопление, Стиральная машина, Сушилка, Товары первой необходимости, Шампунь, Вешалки, "Удобное рабочее место для ноутбука"}, {TV, "Кабельное телевидение". TV », Интернет,« Беспроводной Интернет »,« Кондиционер », Кухня,« Курение разрешено »,« Размещение домашних животных »,« Зуммер / беспроводной домофон », Отопление,« Подходит для семьи / детей »,« Детектор дыма »,« Углерод » монооксида и т. д. Таких столбцов около 10 тыс. Я хочу преобразовать каждое удобство в новый столбец и создавать значения 0 или 1 для каждой записи. Например:

Колонки должны быть созданы, как показано ниже. Беспроводной Интернет Доступ для кресел-каталок Кухня Elivator Зуммер / Беспроводной 1 0 1 1 0

По сути, каждый элемент столбца создает новый столбец, и их значения должны быть равными 0 и 1 в зависимости от того, присутствует ли в столбце удобства или нет.

Я ввел следующие данные: введите здесь описание изображения

и я хочу вывод, как показано ниже:

введите здесь описание изображения


person Rachit Jain    schedule 18.04.2020    source источник
comment
Это может помочь вам начать работу: при условии, что ваш daatframe называется df, вы можете: amenities_clean <- gsub('[{}"]', '', df$amenities) # remove unwanted stuff amenities_unique <- unique(unlist(strsplit(amenities_clean, ","))) # get a list of unique amenities df[amenities_unique] <- NA # set up the columns for each amenity   -  person Chris Ruehlemann    schedule 19.04.2020
comment
@ChrisRuehlemann: Спасибо за приведенный выше код разделения. Это сработало. Теперь моя цель - создать новые столбцы в df с этими значениями, и если значение доступно в исходном столбце с удобствами, то пометьте его как 1, иначе 0.   -  person Rachit Jain    schedule 26.04.2020


Ответы (1)


Вот (довольно сложное) решение (довольно сложной проблемы):

Данные:

df <- data.frame(
  id = 1:2,
  amenities = c('{"Wireless Internet","Wheelchair accessible",Kitchen,Elevator,"Buzzer/wireless intercom",Heating,Washer,Dryer,Essentials,Shampoo,Hangers,"Laptop friendly workspace"}',
                 '{TV,"Cable TV",Internet,"Wireless Internet","Air conditioning",Kitchen,"Smoking allowed","Pets allowed","Buzzer/wireless intercom",Heating,"Family/kid friendly","Smoke detector","Carbon monoxide}'))

Подготовьте данные:

amenities_clean <- gsub('[{}"]', '', df$amenities) # remove unwanted stuff 
amenities_split <- strsplit(amenities_clean, ",") # split rows into individual amenities
amenities_unique <- unique(unlist(strsplit(amenities_clean, ","))) # get a list of unique amenities 
df[amenities_unique] <- NA # set up the columns for each amenity

Теперь по сути анализа с использованием str_detect из пакета stringr:

# record presence/absence of individual amenities in each new column:

library(stringr)
for(i in 1:ncol(df[amenities_unique])){
  for(j in 1:nrow(df)){
    df[amenities_unique][j,i] <- 
      ifelse(str_detect(amenities_split[j], names(df[amenities_unique][i])), 1, 0)
  }
}

Это вызовет предупреждения, но они кажутся незначительными, поскольку результат правильный:

df
  id
1  1
2  2
                                                                                                                                                                                            amenities
1                               {"Wireless Internet","Wheelchair accessible",Kitchen,Elevator,"Buzzer/wireless intercom",Heating,Washer,Dryer,Essentials,Shampoo,Hangers,"Laptop friendly workspace"}
2 {TV,"Cable TV",Internet,"Wireless Internet","Air conditioning",Kitchen,"Smoking allowed","Pets allowed","Buzzer/wireless intercom",Heating,"Family/kid friendly","Smoke detector","Carbon monoxide}
  Wireless Internet Wheelchair accessible Kitchen Elevator Buzzer/wireless intercom Heating Washer Dryer
1                 1                     1       1        1                        1       1      1     1
2                 1                     0       1        0                        1       1      0     0
  Essentials Shampoo Hangers Laptop friendly workspace TV Cable TV Internet Air conditioning Smoking allowed
1          1       1       1                         1  0        0        1                0               0
2          0       0       0                         0  1        1        1                1               1
  Pets allowed Family/kid friendly Smoke detector Carbon monoxide
1            0                   0              0               0
2            1                   1              1               1

ИЗМЕНИТЬ:

В качестве альтернативы и, возможно, более экономично, вместо вложенного forloop вы можете использовать функцию apply, подобную этой (на основе векторов amenities_split и amenities_unique из этапа подготовки первого решения):

cbind(df, t(sapply(amenities_split, function(x) 
  table(factor(x, levels = amenities_unique)))))
person Chris Ruehlemann    schedule 26.04.2020