我是R的新手/可以选择轻松地重新组织数据,并且已经找到了解决方案但却找不到我想要做的事情。 Reshape2的熔化/铸造看起来似乎不起作用,而且我还没有很好地掌握它在这里的因素。
基本上我有一个data.frame,其结构如下所示,带有一个category列,其中每个元素都是一个可变长度的类别列表(更紧凑,因为#columns更大,我实际上有多个category_lists,我想分开):
>mydf
ID category_list xval yval
1 ID1 cat1, cat2, cat3 xnum1 ynum1
2 ID2 cat2, cat3 xnum2 ynum2
3 ID3 cat1 xnum3 ynum3
我想用类别作为因子(和相关的值,即列3/4)进行操作,所以我想我最终需要这样的东西,其中ID和x / y /其他列值是重复的根据类别列表的长度:
ID category xval yval
1 ID1 cat1 xnum1 ynum1
2 ID1 cat2 xnum1 ynum1
3 ID1 cat3 xnum1 ynum1
4 ID2 cat2 xnum2 ynum2
5 ID2 cat3 xnum2 ynum2
6 ID3 cat3 xnum2 ynum2
如果在category_list上有另一个因子/方面的解决方案,那将是一个更简单的解决方案,但我没有遇到支持这个的方法, 例如以下引发错误
>ggplot(mydf, aes(x=x, y=y)) + geom_point() + facet_grid(~cat_list)
layout_base(data,cols,drop = drop)出错: 至少一个图层必须包含用于刻面的所有变量
谢谢!
答案 0 :(得分:9)
答案取决于category_list
的格式。实际上,如果每行list
像
这样的东西mydf <- data.frame(ID = paste0('ID',1:3),
category_list = I(list(c('cat1','cat2','cat3'), c('cat2','cat3'), c('cat1'))),
xval = 1:3, yval = 1:3)
或
library(data.table)
mydf <- as.data.frame(data.table(ID = paste0('ID',1:3),
category_list = list(c('cat1','cat2','cat3'), c('cat2','cat3'), c('cat1')),
xval = 1:3, yval = 1:3) )
然后,您可以使用plyr
和merge
来创建长格式数据
newdf <- merge(mydf, ddply(mydf, .(ID), summarize, cat_list = unlist(category_list)), by = 'ID')
ID category_list xval yval cat_list
1 ID1 cat1, cat2, cat3 1 1 cat1
2 ID1 cat1, cat2, cat3 1 1 cat2
3 ID1 cat1, cat2, cat3 1 1 cat3
4 ID2 cat2, cat3 2 2 cat2
5 ID2 cat2, cat3 2 2 cat3
6 ID3 cat1 3 3 cat1
或不需要merge
do.call(rbind,lapply(split(mydf, mydf$ID), transform, cat_list = unlist(category_list)))
答案 1 :(得分:5)
一个缓慢但看似强大的解决方案:
## Some example data
df <- as.data.frame(cbind(ID = paste0("ID", 1:2),
category_list = list(4:1, 2:3),
xvar = 8:9,
yvar = 10:9))
## Calculate number of times each row of df will be repeated
nn <- sapply(df$category_list, length)
ii <- rep(seq_along(nn), times=nn)
## Reshape data.frame
transform(df[ii,],
category = unlist(df$category_list),
category_list = NULL,
row.names = NULL)
# ID xvar yvar category
# 1 ID1 8 10 4
# 2 ID1 8 10 3
# 3 ID1 8 10 2
# 4 ID1 8 10 1
# 5 ID2 9 9 2
# 6 ID2 9 9 3
答案 2 :(得分:2)
可能性:
x <- read.table(textConnection('
ID category_list xval yval
ID1 "cat1, cat2, cat3" xnum1 ynum1
ID2 "cat2, cat3" xnum2 ynum2
ID3 "cat1" xnum3 ynum3'),
header=TRUE,stringsAsFactors=FALSE)
library(plyr)
ddply(x,"ID",transform,category=strsplit(category_list,",")[[1]])
## ID category_list xval yval category
## 1 ID1 cat1, cat2, cat3 xnum1 ynum1 cat1
## 2 ID1 cat1, cat2, cat3 xnum1 ynum1 cat2
## 3 ID1 cat1, cat2, cat3 xnum1 ynum1 cat3
## 4 ID2 cat2, cat3 xnum2 ynum2 cat2
## 5 ID2 cat2, cat3 xnum2 ynum2 cat3
答案 3 :(得分:0)
这将是一个非普通的方法:
cbind( x[ rep(1:nrow(x),
times=sapply(x$category_list,
function(xx) sapply( strsplit(xx, ","), length) ) ),
-2], # to get rid of the old category column
new_cats = unlist( strsplit(x$category_list, ",") ) )
# this used Bolker's example. If these are factor will need to add `as.character`
ID xval yval new_cats
1 ID1 xnum1 ynum1 cat1
1.1 ID1 xnum1 ynum1 cat2
1.2 ID1 xnum1 ynum1 cat3
2 ID2 xnum2 ynum2 cat2
2.1 ID2 xnum2 ynum2 cat3
3 ID3 xnum3 ynum3 cat1
答案 4 :(得分:0)
使用by
的另一个基本R可能性:
do.call(rbind,
by(mydf,
mydf$ID,
function(x) {
data.frame(
ID=x$ID,
category_list = unlist(strsplit(x$category_list,",")),
xval=x$xval,
yval=x$yval
)
}
)
)
结果:
ID category_list xval yval
ID1.1 ID1 cat1 xnum1 ynum1
ID1.2 ID1 cat2 xnum1 ynum1
ID1.3 ID1 cat3 xnum1 ynum1
ID2.1 ID2 cat2 xnum2 ynum2
ID2.2 ID2 cat3 xnum2 ynum2
ID3 ID3 cat1 xnum3 ynum3
答案 5 :(得分:0)
注意:删除了原始答案,因为我的答案基于与OP实际上不同的数据结构。
list
使用@ mnel的样本数据:
mydf <- data.frame(ID = paste0('ID',1:3),
category_list = I(list(c('cat1','cat2','cat3'), c('cat2','cat3'), c('cat1'))),
xval = 1:3, yval = 1:3)
使用我的“splitstackshape”软件包中的listCol_l
library(splitstackshape)
listCol_l(mydf, "category_list")
# ID xval yval category_list_ul
# 1: ID1 1 1 cat1
# 2: ID1 1 1 cat2
# 3: ID1 1 1 cat3
# 4: ID2 2 2 cat2
# 5: ID2 2 2 cat3
# 6: ID3 3 3 cat1
使用“tidyr”软件包中的unnest
library(tidyr)
unnest(mydf, "category_list")
# ID category_list xval yval
# 1 ID1 cat1 1 1
# 2 ID1 cat2 1 1
# 3 ID1 cat3 1 1
# 4 ID2 cat2 2 2
# 5 ID2 cat3 2 2
# 6 ID3 cat1 3 3
使用@ BenBolker的样本数据:
x <- read.table(textConnection('
ID category_list xval yval
ID1 "cat1, cat2, cat3" xnum1 ynum1
ID2 "cat2, cat3" xnum2 ynum2
ID3 "cat1" xnum3 ynum3'),
header=TRUE,stringsAsFactors=FALSE)
使用我的“splitstackshape”软件包中的cSplit
library(splitstackshape)
cSplit(x, "category_list", ",", "long")
# ID category_list xval yval
# 1: ID1 cat1 xnum1 ynum1
# 2: ID1 cat2 xnum1 ynum1
# 3: ID1 cat3 xnum1 ynum1
# 4: ID2 cat2 xnum2 ynum2
# 5: ID2 cat3 xnum2 ynum2
# 6: ID3 cat1 xnum3 ynum3