我有这样的数据框:
> df <- data.frame(Column1=c("id1", "id2", "id3"), Column2=c("text1,text2,text3", "text4", "text5,text6"), Column3=c("text7", "text8,text9,text10,text11", "text12,text13"))
> df
Column1 Column2 Column3
1 id1 text1,text2,text3 text7
2 id2 text4 text8,text9,text10,text11
3 id3 text5,text6 text12,text13
如何以此格式对其进行转换?
Column1 variable value
1 id1 Column2 text1
2 id1 Column2 text2
3 id1 Column2 text3
4 id2 Column2 text4
5 id3 Column2 text5
6 id3 Column2 text6
7 id1 Column3 text7
8 id2 Column3 text8
9 id2 Column3 text9
10 id2 Column3 text10
11 id2 Column3 text11
12 id3 Column3 text12
13 id3 Column3 text13
我想第一步是melt()
数据框(顺便说一句,我应该担心这个警告吗?):
> library(reshape2)
> mdf <- melt(df, id.vars="Column1", measure.vars=c("Column2", "Column3"))
> mdf
Column1 variable value
1 id1 Column2 text1,text2,text3
2 id2 Column2 text4
3 id3 Column2 text5,text6
4 id1 Column3 text7
5 id2 Column3 text8,text9,text10,text11
6 id3 Column3 text12,text13
Warning message:
attributes are not identical across measure variables; they will be dropped
然后我基本上需要``strsplit()`'value'列并相应地复制行,但我想不出办法去做。
> strsplit(mdf$value, ",")
[[1]]
[1] "text1" "text2" "text3"
[[2]]
[1] "text4"
[[3]]
[1] "text5" "text6"
[[4]]
[1] "text7"
[[5]]
[1] "text8" "text9" "text10" "text11"
[[6]]
[1] "text12" "text13"
任何帮助表示赞赏!感谢。
答案 0 :(得分:6)
data.table
解决方案:
library(data.table)
mdt <- melt(setDT(df), id.vars="Column1")[,strsplit(as.character(value),",",fixed=TRUE),
by=list(Column1,variable)]
结果:
> mdt
Column1 variable V1
1: id1 Column2 text1
2: id1 Column2 text2
3: id1 Column2 text3
....
您还可以使用latest version of data.table
(v1.9.5 +)中的tstrsplit
功能保留value
列的名称,而不是将其重命名为V1
:
mdt <- melt(setDT(df), id.vars="Column1")[,lapply(.SD, function(x) tstrsplit(x, ",", fixed=TRUE)),
by=list(Column1,variable)]
结果:
> mdt
Column1 variable value
1: id1 Column2 text1
2: id1 Column2 text2
3: id1 Column2 text3
....
dplyr
&amp;的另一种解决方案tidyr
:
library(dplyr)
library(tidyr)
mdf <- df %>% gather(variable, value, -Column1) %>%
transform(value = strsplit(as.character(value),",")) %>%
unnest(value)
结果:
> mdf
Column1 variable value
1 id1 Column2 text1
2 id1 Column2 text2
3 id1 Column2 text3
....
使用最新版本的tidyr
,您还可以使用separate_rows
- 函数:
mdf <- df %>%
gather(variable, value, -Column1) %>%
separate_rows(value)
答案 1 :(得分:4)
你可以尝试:
library(reshape2)
来自https://gist.github.com/mrdwab/11380733 的 cSplit
cSplit(melt(df, id.vars="Column1"), "value", ",", "long")
# Column1 variable value
# 1: id1 Column2 text1
# 2: id1 Column2 text2
# 3: id1 Column2 text3
# 4: id2 Column2 text4
# 5: id3 Column2 text5
# 6: id3 Column2 text6
# 7: id1 Column3 text7
# 8: id2 Column3 text8
# 9: id2 Column3 text9
#10: id2 Column3 text10
#11: id2 Column3 text11
#12: id3 Column3 text12
#13: id3 Column3 text13
或者,如果想要坚持CRAN包中可用的功能:
library(reshape2)
library(splitstackshape)
library(dplyr)
select(na.omit(concat.split.multiple(melt(df, id.vars="Column1"), split.col="value", sep=",", direction="long")), -time)
答案 2 :(得分:2)
你到目前为止:
mdf <- melt(df, id.vars="Column1", measure.vars=c("Column2", "Column3"))
values <- strsplit(mdf$value, ",")
现在您需要做的就是创建一个使用mdf
行的索引:
n <- vapply(values, length, integer(1))
index <- rep.int(seq_along(n), n)
然后将其与值组合:
cbind(mdf[index,], unlist(values, use.names = FALSE))
答案 3 :(得分:0)
关于警告:它出现是因为您使用因子变量进行融化。
在您的示例中,您可以避免在 df声明末尾添加stringAsFactors=FALSE
警告:
df <- data.frame(Column1=c("id1", "id2", "id3"), Column2=c("text1,text2,text3", "text4", "text5,text6"), Column3=c("text7", "text8,text9,text10,text11", "text12,text13"), stringsAsFactors=FALSE)