Как создать новый фрейм данных с исходными данными, разделенными; и с разным количеством в категории? - PullRequest
4 голосов
/ 03 июня 2011

У меня есть таблица в следующем формате.

df1 <- data.frame (A=c("aaa", "bbb", "ccc", "ddd"),
                   B=c("111; 222", "333", "444; 555; 666; 777", "888; 999"))

    A                  B
1 aaa           111; 222
2 bbb                333
3 ccc 444; 555; 666; 777
4 ddd           888; 999

Я хочу иметь такой кадр данных:

aaa 111
aaa 222
bbb 333
ccc 444
ccc 555
ccc 666
ccc 777
ddd 888
ddd 999

Я нашел замечательное решение для преобразования аналогичного списка вфрейм данных в предыдущих вопросах переполнения стека.Однако мне сложно конвертировать его из кадра данных с несколькими записями.Как я могу это сделать?

Ответы [ 2 ]

8 голосов
/ 03 июня 2011

Вот простое базовое решение R (пояснение ниже):

spl <- with(df1, strsplit(as.charcter(B), split = "; ", fixed = TRUE))
lens <- sapply(spl, length)
out <- with(df1, data.frame(A = rep(A, lens), B = unlist(spl)))

Что дает нам:

R> out
    A   B
1 aaa 111
2 aaa 222
3 bbb 333
4 ccc 444
5 ccc 555
6 ccc 666
7 ccc 777
8 ddd 888
9 ddd 999

Что делает код? Строка 1:

spl <- with(df1, strsplit(as.character(B), split = "; ", fixed = TRUE))

разбивает каждую строку в B, используя "; " в качестве символов для разделения. Мы используем fixed = TRUE (как предложено @ Marek в комментариях) для ускорения сопоставления и разделения, так как в этом случае нам не нужно сопоставлять с помощью регулярного выражения, мы просто хотим сопоставить на указанная строка. Это дает нам список с разделением различных элементов:

R> spl
[[1]]
[1] "111" "222"

[[2]]
[1] "333"

[[3]]
[1] "444" "555" "666" "777"

[[4]]
[1] "888" "999"

Следующая строка просто подсчитывает, сколько элементов есть в каждом компоненте списка spl

lens <- sapply(spl, length)

, который дает нам векторы длин:

R> lens
[1] 2 1 4 2

Последняя строка решения включает выходные данные двух предыдущих шагов в новый фрейм данных. Хитрость заключается в том, чтобы повторять каждый элемент df1$A lens количество раз; для которого мы используем функцию rep(). Нам также нужно развернуть список spl в вектор, который мы делаем с unlist():

out <- with(df1, data.frame(A = rep(A, lens), B = unlist(spl)))
7 голосов
/ 03 июня 2011

Буквально так же, как первый шаг в моем ответе на ваш предыдущий вопрос:

library(reshape)
x <- melt((strsplit(as.character(df1$B), "; ")))
x <- data.frame("A"=df1[x$L1,1],"B"=x$value)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...