Разбить список на строки при сохранении идентификаторов в r

Я работаю со следующим типом набора данных

    names<-c("Aname","Aname","Bname","Cname","Cname")
    list <- list( c('a, b','b, r','c, g'), c('d,g','e,j'),
    c('d, h','s, q','f,q'), c('d,r ','s, z'),c('d, r','d, r'))
    data<-cbind(names, list)

И хочу разбить каждый элемент списка, а затем связать его с переменной "name". Поэтому набор данных, который я пытаюсь произвести, будет выглядеть так:

Column 1   Column 2
Aname      a
Aname      b
Aname      b
Aname      r
Aname      c

Было много дискуссий о том, как преобразовать список в data.frame, но я изо всех сил пытаюсь найти какие-либо рекомендации о том, как сделать это "внутри" фреймворка данных, где я хотел бы сохранить идентификаторы на одном и том же строка как список (в данном случае - имена). Большое спасибо!

Ответ 1

Вы можете использовать melt

library(reshape2)
melt(lapply(setNames(list, names), function(x)
                      unlist(strsplit(x, ', | |,'))))

Ответ 2

Здесь возможное базовое R-решение

myFunc <- function(x) unlist(strsplit(unlist(x), ", | |,"))

data.frame(Col1 = rep(names, sapply(list, function(x) length(myFunc(x)))), 
           Col2 = myFunc(list))

#     Col1 Col2
# 1  Aname    a
# 2  Aname    b
# 3  Aname    b
# 4  Aname    r
# 5  Aname    c
# 6  Aname    g
# 7  Aname    d
# 8  Aname    g
# 9  Aname    e
# 10 Aname    j
# 11 Bname    d
# 12 Bname    h
# 13 Bname    s
# 14 Bname    q
# 15 Bname    f
# 16 Bname    q
# 17 Cname    d
# 18 Cname    r
# 19 Cname    s
# 20 Cname    z
# 21 Cname    d
# 22 Cname    r
# 23 Cname    d
# 24 Cname    r

Ответ 3

Еще один подход с splitstackshape - его функция cSplit по умолчанию блокирует пробелы, смежные с разделителем.

library(splitstackshape)
lengths <- sapply(data[, 2], length)
nameslist <- unlist(rep(data[, 1], lengths))
df1 <- data.frame(names = nameslist, chars = unlist(data[, 2]))
cSplit(df1, "chars", sep = ",", direction = "long")

Или за комментарий Ананды, просто:

cSplit(data.table(names = data[, "names"], list = sapply(data[, "list"], toString)),
 "list", ",", "long")

Результат:

    names chars
 1: Aname     a
 2: Aname     b
 3: Aname     b
 4: Aname     r
 5: Aname     c
 6: Aname     g
 7: Aname     d
 8: Aname     g
 9: Aname     e
10: Aname     j
11: Bname     d
12: Bname     h
13: Bname     s
14: Bname     q
15: Bname     f
16: Bname     q
17: Cname     d
18: Cname     r
19: Cname     s
20: Cname     z
21: Cname     d
22: Cname     r
23: Cname     d
24: Cname     r

Если вы не хотите, чтобы результат был как data.table, вы можете обернуть последнюю строку в as.data.frame().

Ответ 4

Вот как это сделать с помощью dplyr/tidyr. Идея состоит в том, чтобы преобразовать каждый элемент list в самый список (из вектора символов, который он есть в настоящее время), а затем вызвать очень полезную функцию unnest

library(dplyr)
library(tidyr)
data.frame(data) %>% 
    unnest(list) %>% 
    mutate(list = strsplit(list, ",")) %>%
    unnest(list)
#   names list
#1  Aname    a
#2  Aname    b
#3  Aname    b
#4  Aname    r
#5  Aname    c
#6  Aname    g
#7  Aname    d
#8  Aname    g
#9  Aname    e
#10 Aname    j
#11 Bname    d
#12 Bname    h
#13 Bname    s
#14 Bname    q
#15 Bname    f
#16 Bname    q
#17 Cname    d
#18 Cname   r 
#19 Cname    s
#20 Cname    z
#21 Cname    d
#22 Cname    r
#23 Cname    d
#24 Cname    r

(Чтобы избавиться от лишних пробелов, при необходимости вы можете добавить %>% mutate(list = gsub(" ", "", list)) в цепочку команд.)

Ответ 5

OP объединяет два вопроса вместе.

Ответ на первый - это очистка данных. Например, копирование функции @DavidArenburg:

myFunc <- function(x) unlist(strsplit(unlist(x), ", | |,")) 
clean  <- sapply(list, myFunc)

И вторым шагом будет стек:

stack(setNames(clean,names))