从数据框中"解压缩"因子列表

wil*_*ter 6 r dataframe reshape2

我是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
Run Code Online (Sandbox Code Playgroud)

我想用类别作为因子(和相关的值,即列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
Run Code Online (Sandbox Code Playgroud)

如果在category_list上有另一个因子/方面的解决方案,那将是一个更简单的解决方案,但我没有遇到支持这个的方法,例如以下引发错误

>ggplot(mydf, aes(x=x, y=y)) + geom_point() + facet_grid(~cat_list)
Run Code Online (Sandbox Code Playgroud)

layout_base中的错误(data,cols,drop = drop):至少一个图层必须包含用于构面的所有变量

谢谢!

mne*_*nel 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)
Run Code Online (Sandbox Code Playgroud)

要么

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) )
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用plyrmerge创建长格式数据

 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
Run Code Online (Sandbox Code Playgroud)

或者不需要的非plyr方法 merge

 do.call(rbind,lapply(split(mydf, mydf$ID), transform, cat_list = unlist(category_list)))
Run Code Online (Sandbox Code Playgroud)


Jos*_*ien 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
Run Code Online (Sandbox Code Playgroud)