Разделите строки с разделителями в столбце и вставьте в качестве новых строк
У меня есть кадр данных:
+-----+-------+
| V1 | V2 |
+-----+-------+
| 1 | a,b,c |
| 2 | a,c |
| 3 | b,d |
| 4 | e,f |
| . | . |
+-----+-------+
Каждый из алфавитов является символом, разделенным запятой. Я хотел бы разделить V2 на каждую запятую и вставить разделенные строки в виде новых строк. Например, желаемый результат будет:
+----+----+
| V1 | V2 |
+----+----+
| 1 | a |
| 1 | b |
| 1 | c |
| 2 | a |
| 2 | c |
| 3 | b |
| 3 | d |
| 4 | e |
| 4 | f |
+----+----+
Я пытаюсь использовать strsplit()
, чтобы сначала наплевать V2, а затем перечислить список в фрейм данных. Это не сработало. Любая помощь будет оценена.
Ответы
Ответ 1
Вот еще один способ сделать это.
df <- read.table(textConnection("1|a,b,c\n2|a,c\n3|b,d\n4|e,f"), header = F, sep = "|", stringsAsFactors = F)
df
## V1 V2
## 1 1 a,b,c
## 2 2 a,c
## 3 3 b,d
## 4 4 e,f
s <- strsplit(df$V2, split = ",")
data.frame(V1 = rep(df$V1, sapply(s, length)), V2 = unlist(s))
## V1 V2
## 1 1 a
## 2 1 b
## 3 1 c
## 4 2 a
## 5 2 c
## 6 3 b
## 7 3 d
## 8 4 e
## 9 4 f
Ответ 2
По состоянию на декабрь 2014 это можно сделать, используя функцию unsest из пакета Hadley Wickham tidyr (см. примечания к выпуску http://blog.rstudio.org/2014/12/08/tidyr-0-2-0/)
> library(tidyr)
> library(dplyr)
> mydf
V1 V2
2 1 a,b,c
3 2 a,c
4 3 b,d
5 4 e,f
6 . .
> mydf %>%
mutate(V2 = strsplit(as.character(V2), ",")) %>%
unnest(V2)
V1 V2
1 1 a
2 1 b
3 1 c
4 2 a
5 2 c
6 3 b
7 3 d
8 4 e
9 4 f
10 . .
Ответ 3
Здесь a data.table
решение:
d.df <- read.table(header=T, text="V1 | V2
1 | a,b,c
2 | a,c
3 | b,d
4 | e,f", stringsAsFactors=F, sep="|", strip.white = TRUE)
require(data.table)
d.dt <- data.table(d.df, key="V1")
out <- d.dt[, list(V2 = unlist(strsplit(V2, ","))), by=V1]
# V1 V2
# 1: 1 a
# 2: 1 b
# 3: 1 c
# 4: 2 a
# 5: 2 c
# 6: 3 b
# 7: 3 d
# 8: 4 e
# 9: 4 f
> sapply(out$V2, nchar) # (or simply nchar(out$V2))
# a b c a c b d e f
# 1 1 1 1 1 1 1 1 1
Ответ 4
Теперь вы можете использовать tidyr 0.5.0 separate_rows
вместо strsplit
+ unnest
.
Например:
library(tidyr)
(df <- read.table(textConnection("1|a,b,c\n2|a,c\n3|b,d\n4|e,f"), header = F, sep = "|", stringsAsFactors = F))
V1 V2
1 1 a,b,c
2 2 a,c
3 3 b,d
4 4 e,f
separate_rows(df, V2)
дает:
V1 V2
1 1 a
2 1 b
3 1 c
4 2 a
5 2 c
6 3 b
7 3 d
8 4 e
9 4 f
См. ссылку: https://blog.rstudio.org/2016/06/13/tidyr-0-5-0/
Ответ 5
Вы можете рассмотреть cSplit
с помощью direction = "long"
из моего пакета splitstackshape.
Использование:
cSplit(mydf, "V2", ",", "long")
## V1 V2
## 1: 1 a
## 2: 1 b
## 3: 1 c
## 4: 2 a
## 5: 2 c
## 6: 3 b
## 7: 3 d
## 8: 4 e
## 9: 4 f
Старый ответ....
Вот один подход с использованием базы R. Предполагается, что мы начинаем с data.frame
с именем "mydf". Он использует read.csv
для чтения во втором столбце как отдельный data.frame
, который мы объединяем с первым столбцом из ваших исходных данных. Наконец, вы используете reshape
для преобразования данных в длинную форму.
temp <- data.frame(Ind = mydf$V1,
read.csv(text = as.character(mydf$V2), header = FALSE))
temp1 <- reshape(temp, direction = "long", idvar = "Ind",
timevar = "time", varying = 2:ncol(temp), sep = "")
temp1[!temp1$V == "", c("Ind", "V")]
# Ind V
# 1.1 1 a
# 2.1 2 a
# 3.1 3 b
# 4.1 4 e
# 1.2 1 b
# 2.2 2 c
# 3.2 3 d
# 4.2 4 f
# 1.3 1 c
Еще одна довольно прямая альтернатива:
stack(
setNames(
sapply(strsplit(mydf$V2, ","),
function(x) gsub("^\\s|\\s$", "", x)), mydf$V1))
values ind
1 a 1
2 b 1
3 c 1
4 a 2
5 c 2
6 b 3
7 d 3
8 e 4
9 f 4
Ответ 6
Другое решение data.table
, которое не полагается на существование каких-либо уникальных полей в исходных данных.
DT = data.table(read.table(header=T, text="blah | splitme
T | a,b,c
T | a,c
F | b,d
F | e,f", stringsAsFactors=F, sep="|", strip.white = TRUE))
DT[,.( blah
, splitme
, splitted=unlist(strsplit(splitme, ","))
),by=seq_len(nrow(DT))]
Важная вещь by=seq_len(nrow(DT))
, это "поддельный" уникальный идентификатор, на котором происходит расщепление. Заманчиво использовать by=.I
вместо этого, так как его нужно определить одинаково, но .I
кажется волшебной вещью, которая меняет ее значение, лучше придерживаться by=seq_len(nrow(DT))
На выходе есть три столбца. Мы просто называем два существующих столбца, а затем вычисляем третий как разделенный
.( blah # first column of original
, splitme # second column of original
, splitted = unlist(strsplit(splitme, ","))
)