将所有列堆叠成两列,并在 R 中使用分类列

Stack all columns into two columns with categorical column in R

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

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

我想要做的是将所有列 'stack' 分成两个列,分别称为 "Model" 和 "Data"。这些列包含各个 "Model" 和 "Data" 列的每个唯一组合。我还想创建一个对数据进行分类的索引列。我要创建的数据集是:

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

我认为必须能够使用重塑包中的一些工具来完成,但我无法理解如何使用 "Model" 和 [ 的所有独特组合在其中获取索引列=23=] 列。

值得注意的是我的实际数据集有 9 "Model" 列和 15 "Data" 列。

谢谢。

你可以试试

  1. 正在创建 "column names" (combn(colnames...))
  2. 的组合
  3. 从 "indx" 中删除属于同一类型的名称(即 Data_A、Data_B 或 Model_A、Model_B)
  4. 子集 "indx" 以创建 "indx2"
  5. split "indx2" 通过 "columns" 创建列表 ("lst")
  6. 更改 "lst" 的名称以标识组 ("Cat")
  7. 根据 "lst" 名称对 "dat" 进行子集化,并使用 tidyr 中的 unnest 来绑定列表元素。

    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
    

或者您可以使用 expand.griddata.table

中的 rbindlist
    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]])}))

这也是一个可能的解决方案:

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 两次,它为模型和数据的每个组合创建一个数据框,将适当的名称放在第一列中。最后一步是将所有这些位于双层嵌套列表中的数据框放入单个数据框中。