Удаление столбцов по группам

У меня есть кадр данных в следующем формате:

id | name               | logs                                  
---+--------------------+-----------------------------------------
84 |          "zibaroo" |                             "C47931038" 
12 | "fabien kelyarsky" | c("C47331040", "B19412225", "B18511449")
96 |     "mitra lutsko" |              c("F19712226", "A18311450")
34 |       "PaulSandoz" |                             "A47431044" 
65 |       "BeamVision" |                             "D47531045" 

Как вы видите, столбец «журналы» включает в себя векторы строк в каждой ячейке.

Есть ли эффективный способ преобразовать фрейм данных в длинный формат (одно наблюдение в строке) без промежуточного этапа разделения «журналов» на несколько столбцов?

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

Другими словами, мне нужно следующее:

id | name               | log                                 
---+--------------------+------------
84 |          "zibaroo" | "C47931038" 
12 | "fabien kelyarsky" | "C47331040"
12 | "fabien kelyarsky" | "B19412225"
12 | "fabien kelyarsky" | "B18511449"
96 |     "mitra lutsko" | "F19712226"
96 |     "mitra lutsko" | "A18311450"
34 |       "PaulSandoz" | "A47431044" 
65 |       "BeamVision" | "D47531045" 

Вот dput раздела реального фрейма данных:

structure(list(id = 148:157, name = c("avihil1", "Niarfe", "doug henderson", 
"nick tan", "madisp", "woodbusy", "kevinhcross", "cylol", "andrewarrow", 
"gstavrev"), logs = list("Z47331572", "Z47031573", c("F47531574", 
"B195945", "D186871", "S192939", "S182865", "G19539045"), c("A47231575", 
"A190933", "C181859"), "F47431576", c("B47231577", "D193936", 
"Q184862"), "Y47331579", c("A47531580", "Z195944", "B185870"), 
"N47731581", "E47231582")), .Names = c("id", "name", "logs"
), row.names = 149:158, class = "data.frame")

person retrography    schedule 21.07.2015    source источник
comment
Предоставьте dput из (части) ваших данных.   -  person SabDeM    schedule 22.07.2015
comment
Это действительно так выглядит текстовый файл или это ваше воображение того, что может содержать объект R-данных? Если последнее, то вместо этого вы должны опубликовать вывод dput(object).   -  person IRTFM    schedule 22.07.2015
comment
вам, вероятно, нужно library(splitstackshape); cSplit(data, 'log', ',', direction = 'long')   -  person Veerendra Gadekar    schedule 22.07.2015
comment
@SabDeM , @BondedDuest : я добавил dput   -  person retrography    schedule 22.07.2015


Ответы (4)


Это идеальный случай для тидыра:

library(tidyr)
library(dplyr)
dat %>% unnest(logs)
person jeremycg    schedule 21.07.2015
comment
Проблема здесь в том (и я только что это заметил), что у некоторых участников нет журналов (переменная logs равна нулю или пустому вектору/списку). Unnest подавляет эти записи и, похоже, не предлагает никаких вариантов для переопределения этого поведения по умолчанию. Любое предложение? - person retrography; 22.07.2015
comment
Вы можете сначала попробовать изменить их на NA - dat$logs[sapply(dat$logs,length)==0]‹-NA, вызов без вложения. - person jeremycg; 22.07.2015
comment
Я всегда забываю, что NA и NULL — это два разных зверя в R. Плохие привычки, связанные с базами данных. Спасибо. Работает отлично. - person retrography; 23.07.2015

Использование listCol_l из splitstackshape может быть здесь хорошим вариантом, так как столбец «журналы» в data.frame является list

library(splitstackshape)
listCol_l(df, 'logs')

 #    id           name   logs_ul
 #1: 148        avihil1 Z47331572
 #2: 149         Niarfe Z47031573
 #3: 150 doug henderson F47531574
 #4: 150 doug henderson   B195945
 #5: 150 doug henderson   D186871
 #6: 150 doug henderson   S192939
 #7: 150 doug henderson   S182865
 #8: 150 doug henderson G19539045
 #9: 151       nick tan A47231575
#10: 151       nick tan   A190933
#11: 151       nick tan   C181859
#12: 152         madisp F47431576
#13: 153       woodbusy B47231577
#14: 153       woodbusy   D193936
#15: 153       woodbusy   Q184862
#16: 154    kevinhcross Y47331579
#17: 155          cylol A47531580
#18: 155          cylol   Z195944
#19: 155          cylol   B185870
#20: 156    andrewarrow N47731581
#21: 157       gstavrev E47231582
person Veerendra Gadekar    schedule 21.07.2015

Просто чтобы показать еще один вариант

library(data.table)
setDT(df)[, .(logs = unlist(logs)), by = .(id, name)]
person David Arenburg    schedule 21.07.2015

Другой data.table вариант

library(data.table)
dt <- data.table(df)
dt[,.(id,logs=logs[[1]]), by = name]
person Fabio Correa    schedule 27.11.2018