将所有列堆叠为两列,其中R中包含分类列

时间:2015-01-15 10:12:32

标签: r reshape

首先让我创建一些测试数据:

dat <- data.frame(Model_A=rnorm(10, 10), Model_B=rnorm(10, 12), Data_A=rnorm(10, 11), 
Data_B=rnorm(10, 13))

# this produces the following
dat

     Model_A   Model_B    Data_A   Data_B
1  10.421684 13.201037 11.711313 13.18555
2   9.529258 11.086655 12.015787 14.13989
3   9.483633 10.697859 10.123176 15.50154
4  10.623490 11.171480  9.406222 12.56696
5  10.460739 10.925262 10.640612 11.98662
6   9.351494 10.276617 11.717629 13.00709
7  10.264206 11.587463 10.653878 13.33615
8  10.183569 13.187894 10.127552 13.87615
9   8.832003  9.739279 10.970686 13.26850
10 10.932207 11.974472 10.374939 12.11782

我希望能够做的是将所有列“堆叠”成两个名为“模型”和“数据”的列。列包含各个“模型”和“数据”列的唯一组合。我还想创建一个对数据进行分类的索引列。我想创建的数据集是:

Cat             Model       Data
Model_A_Data_A  10.421684   11.711313
Model_A_Data_A  9.529258    12.015787
Model_A_Data_A  9.483633    10.123176
Model_A_Data_A  10.62349    9.406222
Model_A_Data_A  10.460739   10.640612
Model_A_Data_A  9.351494    11.717629
Model_A_Data_A  10.264206   10.653878
Model_A_Data_A  10.183569   10.127552
Model_A_Data_A  8.832003    10.970686
Model_A_Data_A  10.932207   10.374939
Model_A_Data_B  10.421684   13.18555
Model_A_Data_B  9.529258    14.13989
Model_A_Data_B  9.483633    15.50154
Model_A_Data_B  10.62349    12.56696
Model_A_Data_B  10.460739   11.98662
Model_A_Data_B  9.351494    13.00709
Model_A_Data_B  10.264206   13.33615
Model_A_Data_B  10.183569   13.87615
Model_A_Data_B  8.832003    13.2685
Model_A_Data_B  10.932207   12.11782
Model_B_Data_A  13.201037   11.711313
Model_B_Data_A  11.086655   12.015787
Model_B_Data_A  10.697859   10.123176
Model_B_Data_A  11.17148    9.406222
Model_B_Data_A  10.925262   10.640612
Model_B_Data_A  10.276617   11.717629
Model_B_Data_A  11.587463   10.653878
Model_B_Data_A  13.187894   10.127552
Model_B_Data_A  9.739279    10.970686
Model_B_Data_A  11.974472   10.374939
Model_B_Data_B  13.201037   13.18555
Model_B_Data_B  11.086655   14.13989
Model_B_Data_B  10.697859   15.50154
Model_B_Data_B  11.17148    12.56696
Model_B_Data_B  10.925262   11.98662
Model_B_Data_B  10.276617   13.00709
Model_B_Data_B  11.587463   13.33615
Model_B_Data_B  13.187894   13.87615
Model_B_Data_B  9.739279    13.2685
Model_B_Data_B  11.974472   12.11782

我认为必须能够使用reshape包中的一些工具来完成,但我无法理解如何使用“Model”和“Data”列的所有独特组合来获取索引列。

值得注意的是,我的实际数据集中有9个“模型”columans和15个“数据”列。

谢谢。

2 个答案:

答案 0 :(得分:1)

您可以尝试

  1. 创建“列名称”(combn(colnames...)
  2. 的组合
  3. 从“indx”中删除属于同一类型的名称(即Data_A,Data_B或Model_A,Model_B)
  4. 将“indx”子集设置为“indx2”
  5. split“indx2”by“columns”创建列表(“lst”)
  6. 更改“lst”的名称以标识组(“Cat”)
  7. 根据“lst”名称对“dat”进行子集,并使用unnest中的tidyr来搜索列表元素。

    library(tidyr)
    indx <- combn(colnames(dat),2)
    indx1 <- apply(indx, 2, function(x) length(unique(sub('_.*', '', x)))>1)
    indx2 <- indx[,indx1]
    lst <- split(indx2, col(indx2))
    names(lst) <- apply(indx2, 2, paste, collapse='_')
    
    res <-  unnest(lapply(lst,function(x) {
                   x1 <- dat[x] 
                   colnames(x1) <- c('Model', 'Data')
                   x1}), Cat)
    head(res,2)
    #           Cat     Model      Data
    #1 Model_A_Data_A  9.676133  9.491202
    #2 Model_A_Data_A 11.599942 10.446249
    
  8. 或者您可以使用expand.gridrbindlist

    中的data.table
        indx <- expand.grid(split(colnames(dat), 
                      sub("_.*", '', colnames(dat))))[2:1]
        indx1 <- transform(indx, Cat=paste(Model, Data, sep="_"))
    
        library(data.table)
        res1 <-  rbindlist(apply(indx1, 1, function(x) {
                    x1 <- unname(x)
                  data.frame(Cat=x1[3],dat[x1[1:2]])}))
    

答案 1 :(得分:1)

这也是一个可能的选择:

dat <- data.frame(Model_A=rnorm(10, 10), Model_B=rnorm(10, 12), Data_A=rnorm(10, 11), 
              Data_B=rnorm(10, 13))
model.names <- grep("Model",names(dat),value=TRUE)
data.names <- grep("Data",names(dat),value=TRUE)

new.dat <- 
lapply(model.names,function(m) {
  lapply(data.names,function(d) {
    md <- cbind(dat[,m],dat[,d])
    md.name <- rep(paste0(m,"_",d),nrow(md))
    data.frame(md.name,md)
  })
 })

new.dat <- do.call(rbind,lapply(new.dat,function(l) do.call(rbind,l)))
names(new.dat) <- c("Cat","Model","Data")

首先,它提取模型和数据列的名称。 Aferwards,使用lapply两次,它为模型和数据的每个组合创建一个数据框,在第一列中放置适当的名称。最后一步是将所有这些数据帧放在一个双重嵌套列表中,放在一个数据框中。