R Data.Table 按列名重塑

R Data.Table Reshape By Col Name

data1=data.frame(Grade=c(1,2,3,4,5),
                 Cat_a=c(9,6,6,8,8),
                 Cat_b=c(8,5,9,10,8),
                 Dog_a=c(7,5,8,8,5),
                 Dog_b=c(9,8,8,8,10),
                 Fox_a=c(6,7,8,8,6),
                 Fox_b=c(7,6,8,6,9))

data2=data.frame(Grade=c(1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5),
                 Animal=c('Cat','Cat','Cat','Cat','Cat','Dog','Dog','Dog','Dog','Dog','Fox','Fox','Fox','Fox','Fox','Cat','Cat','Cat','Cat','Cat','Dog','Dog','Dog','Dog','Dog','Fox','Fox','Fox','Fox','Fox'),
                 Group=c('A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','B','B','B','B','B','B','B','B','B','B','B','B','B','B','B'),
                 Score=c(9,6,6,8,8,7,5,8,8,5,6,7,8,8,6,8,5,9,10,8,9,8,8,8,10,7,6,8,6,9))

我有 'data1' 并希望创建 'data2' 将其从宽文件转换为长文件,如图所示。我尝试了典型的重塑,但不确定如何以这种方式清理它并使用“_a”和“_b”作为分隔符或 ID 名称。

您可以使用 tstrsplitmelt 产生的列拆分为两列 AnimalGroup

library(data.table)    
setDT(data1)

melt(data1, 'Grade', value.name = 'Score'
     )[, c('Animal', 'Group') := tstrsplit(variable, '_')
     ][, variable := NULL][]

#     Grade Score Animal Group
#  1:     1     9    Cat     a
#  2:     2     6    Cat     a
#  3:     3     6    Cat     a
#  4:     4     8    Cat     a
#  5:     5     8    Cat     a
#  6:     1     8    Cat     b
#  7:     2     5    Cat     b
#  8:     3     9    Cat     b
#  9:     4    10    Cat     b
# 10:     5     8    Cat     b
# 11:     1     7    Dog     a
# 12:     2     5    Dog     a
# 13:     3     8    Dog     a
# 14:     4     8    Dog     a
# 15:     5     5    Dog     a
# 16:     1     9    Dog     b
# 17:     2     8    Dog     b
# 18:     3     8    Dog     b
# 19:     4     8    Dog     b
# 20:     5    10    Dog     b
# 21:     1     6    Fox     a
# 22:     2     7    Fox     a
# 23:     3     8    Fox     a
# 24:     4     8    Fox     a
# 25:     5     6    Fox     a
# 26:     1     7    Fox     b
# 27:     2     6    Fox     b
# 28:     3     8    Fox     b
# 29:     4     6    Fox     b
# 30:     5     9    Fox     b
#     Grade Score Animal Group

选项tidyverse

library(tidyr)
library(dplyr)
pivot_longer(data1, cols = -Grade, names_to = "Animal",
      values_to = 'Score') %>%
    separate(Animal, into = c("Animal", "Group"))