使用 reshape2 重塑带分隔符的数据

Reshape data with separator using reshape2

我正在尝试使用 reshape2 包来重塑我的数据,但出现错误。我的数据如下:

mydata<-read.csv("Data.csv")
head(mydata)    
      Date  A.Price B.Price C.Price A.Rating B.Rating C.Rating
31/01/2012    1.273    3.11   1.215        5        4        3  
29/02/2012    1.393    3.19   1.205       10        8        7  
30/03/2012    1.367    3.15   1.076     10.5      9.5      7.5  

我的目标是将其重塑为:

Date       ID  Price  Rating  
31/01/2012  A  1.273  5  
31/01/2012  B  3.11  4  
31/01/2012  C  1.215  3  
29/02/2012  A  1.393  10  
29/02/2012  B  3.19  8  
....  

到目前为止我的代码是:

mydata$ID <- sequence(nrow(mydata))  
out<-melt(reshape(mydata, direction = "long", 
  timevar = "Group", varying = names(mydata), sep = "."), 
       id.vars = c("ID", "Price","Rating"))

但我收到错误消息:

Error in reshapeLong(data, idvar = idvar, timevar = timevar, varying = varying, : 'varying' arguments must be the same length

关于如何解决这个问题有什么想法吗?

我们可以使用 data.table 中的 melt,它可以包含多个 measure

library(data.table)
dM <- melt(setDT(mydata), measure=patterns('Price', 'Rating'), 
    variable.name='ID', value.name=c('Price', 'Rating'))

默认情况下,'variable'(即'ID')列输出为数字索引。我们可以使用 sub 从列名中获取前缀并更新 'ID' 列。

dM[, ID:= sub('\..*', '', names(mydata)[-1])[ID]]
dM
#         Date ID Price Rating
#1: 31/01/2012  A 1.273    5.0
#2: 29/02/2012  A 1.393   10.0
#3: 30/03/2012  A 1.367   10.5
#4: 31/01/2012  B 3.110    4.0
#5: 29/02/2012  B 3.190    8.0
#6: 30/03/2012  B 3.150    9.5
#7: 31/01/2012  C 1.215    3.0
#8: 29/02/2012  C 1.205    7.0
#9: 30/03/2012  C 1.076    7.5

或使用 base R 中的 reshape 并将 varying 指定为列索引列表。我们可以用 grep

得到索引
nm1 <- unique(sub('.*\.', '', names(mydata)[-1])) 
res <- reshape(mydata, direction='long', varying= lapply(nm1, 
           grep, names(mydata)))
row.names(res) <- NULL
head(res)
#        Date time A.Price A.Rating id
#1 31/01/2012    1   1.273      5.0  1
#2 29/02/2012    1   1.393     10.0  2
#3 30/03/2012    1   1.367     10.5  3
#4 31/01/2012    2   3.110      4.0  1
#5 29/02/2012    2   3.190      8.0  2
#6 30/03/2012    2   3.150      9.5  3

或者另一个选项是 merged.stack 来自 library(splitstackshape)。如果我们需要根据列名中的后缀部分转成'long'格式,则用sub获取列名的后缀,使用var.stubs中的unique元素以及将 sep 指定为 'var.stubsinmerged.stack`.

library(splitstackshape)
nm1 <- unique(sub('.*\.', '', names(mydata)[-1]))#from above
merged.stack(mydata, var.stubs =nm1, atStart=FALSE, 
    sep='var.stubs')[, .time_1:= sub('[.]+', '', .time_1)][]
#         Date .time_1 Price Rating
#1: 29/02/2012       A 1.393   10.0
#2: 29/02/2012       B 3.190    8.0
#3: 29/02/2012       C 1.205    7.0
#4: 30/03/2012       A 1.367   10.5
#5: 30/03/2012       B 3.150    9.5
#6: 30/03/2012       C 1.076    7.5
#7: 31/01/2012       A 1.273    5.0
#8: 31/01/2012       B 3.110    4.0
#9: 31/01/2012       C 1.215    3.0