Изменение формы данных с помощью разделителя с использованием 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"))

но я получаю ошибку:

Ошибка в reshapeLong(данные, idvar = idvar, timevar = timevar, варьирование = варьирование,: "переменные" аргументы должны быть одинаковой длины

Есть идеи, как это решить?

1 ответ

Решение

Мы можем использовать melt от data.table который может занять несколько measure столбцы

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

По умолчанию столбец "переменная" (т.е. "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

Или используя reshape от base R и укажите 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), Если нам нужно преобразовать в "длинный" формат, основанный на части суффикса в именах столбцов, получите суффикс имен столбцов с помощью subи использовать unique элементы в var.stubs наряду с указанием 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
Другие вопросы по тегам