Преобразование неопрятного и несбалансированного набора данных из широкого в длинный

У меня есть набор данных (данные), который выглядит так:

ID,ABC.BC,ABC.PL,DEF.BC,DEF.M,GHI.PL
SB0005,C01,D20,C01a,C01b,D20
BC0013,C05,D5,C05a,NA,D5

Я хочу изменить его из широкого в длинный формат, чтобы получить что-то вроде этого:

ID,FC,Type,Var
SB0005,ABC,BC,C01
SB0005,ABC,PL,D20
SB0005,DEF,BC,C01a
SB0005,DEF,M,C01b
SB0005,GHI,PL,D20
BC0013,ABC,BC,C05
BC0013,ABC,PL,D5
BC0013,DEF,BC,C05a
# BC0013,DEF,M,NA (This row need not be in the dataset as I will remove it later)
BC0013,GHI,PL,D5

Обычный пакет reshape не работает, так как набор данных несбалансирован. Я также пробовал Reshape из splitstackshape, но это не дает мне того, что я хочу.

library(splitstackshape)
vary <- grep("\\.BC$|\\.PL$|\\.M$", names(data))
stubs <- unique(sub("\\..*$", "", names(data[vary])))
Reshape(data, id.vars=c("ID"), var.stubs=stubs, sep=".")

ID,time,ABC,DEF,GHI
SB0005,1,C01,C01a,D20
BC0013,1,C05,C05a,D5
SB0005,2,D20,C01b,NA
BC0013,2,D5,NA,NA
SB0005,3,NA,NA,NA
BC0013,3,NA,NA,NA

Оцените любые предложения, спасибо!

Предоставление вывода dput(data) по запросу

structure(list(ID = structure(c(2L, 1L), .Label = c("BC0013", 
"SB0005"), class = "factor"), ABC.BC = structure(1:2, .Label = c("C01", 
"C05"), class = "factor"), ABC.PL = structure(1:2, .Label = c("D20", 
"D5"), class = "factor"), DEF.BC = structure(1:2, .Label = c("C01a", 
"C05a"), class = "factor"), DEF.M = structure(1:2, .Label = c("C01b", 
"NA"), class = "factor"), GHI.PL = structure(1:2, .Label = c("D20", 
"D5"), class = "factor")), .Names = c("ID", "ABC.BC", "ABC.PL", 
"DEF.BC", "DEF.M", "GHI.PL"), row.names = c(NA, -2L), class = "data.frame")

person phusion    schedule 27.09.2016    source источник
comment
Предоставьте вывод dput(data) в своем вопросе, чтобы мы могли воспроизвести ваши усилия.   -  person Chrisss    schedule 27.09.2016
comment
Как неуравновешенный? Вы имеете в виду NA, который хотите удалить? Кроме того, должна ли последняя строка ожидаемого вывода иметь D5, а не D20?   -  person mathematical.coffee    schedule 27.09.2016
comment
Вы правы, я исправил ошибку, спасибо. Это несбалансировано, потому что BC, PL и M появляются не во всех FC, например. BC появляется в ABC и DEF, а не в GHI.   -  person phusion    schedule 27.09.2016


Ответы (1)


Сначала вам нужно преобразовать ваши данные в длинный формат, а затем вы можете разделить столбец переменных на столбцы. С splitstackshape вы можете сделать:

library(splitstackshape) # this will also load 'data.table' from which the 'melt' function is used
cSplit(melt(mydf, id.vars = 'ID'), 
       'variable', 
       sep = '.', 
       direction = 'wide')[!is.na(value)]

что приводит к:

                          ID value variable_1 variable_2
1:                    SB0005   C01        ABC         BC
2:                    BC0013   C05        ABC         BC
3:                    SB0005   D20        ABC         PL
4:                    BC0013    D5        ABC         PL
5:                    SB0005  C01a        DEF         BC
6:                    BC0013  C05a        DEF         BC
7:                    SB0005  C01b        DEF          M
8:                    SB0005   D20        GHI         PL
9:                    BC0013    D5        GHI         PL

Альтернатива с tidyr:

library(tidyr)
mydf %>% 
  gather(var, val, -ID) %>% 
  separate(var, c('FC','Type')) %>% 
  filter(!is.na(val))
person Jaap    schedule 27.09.2016