Ответ 1
Вы можете использовать melt
library(reshape2)
melt(lapply(setNames(list, names), function(x)
unlist(strsplit(x, ', | |,'))))
Я работаю со следующим типом набора данных
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, но я изо всех сил пытаюсь найти какие-либо рекомендации о том, как сделать это "внутри" фреймворка данных, где я хотел бы сохранить идентификаторы на одном и том же строка как список (в данном случае - имена). Большое спасибо!
Вы можете использовать melt
library(reshape2)
melt(lapply(setNames(list, names), function(x)
unlist(strsplit(x, ', | |,'))))
Здесь возможное базовое 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
Еще один подход с 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()
.
Вот как это сделать с помощью 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))
в цепочку команд.)
OP объединяет два вопроса вместе.
Ответ на первый - это очистка данных. Например, копирование функции @DavidArenburg:
myFunc <- function(x) unlist(strsplit(unlist(x), ", | |,"))
clean <- sapply(list, myFunc)
И вторым шагом будет стек:
stack(setNames(clean,names))