Переформируйте широкий формат, к многоколоночному длинному формату
Я хочу изменить форму набора данных широкого формата, который имеет несколько тестов, которые измеряются в 3 временных точках:
ID Test Year Fall Spring Winter
1 1 2008 15 16 19
1 1 2009 12 13 27
1 2 2008 22 22 24
1 2 2009 10 14 20
2 1 2008 12 13 25
2 1 2009 16 14 21
2 2 2008 13 11 29
2 2 2009 23 20 26
3 1 2008 11 12 22
3 1 2009 13 11 27
3 2 2008 17 12 23
3 2 2009 14 9 31
В набор данных, который разделяет тесты по столбцам, но преобразует время измерения в длинный формат для каждого из новых столбцов следующим образом:
ID Year Time Test1 Test2
1 2008 Fall 15 22
1 2008 Spring 16 22
1 2008 Winter 19 24
1 2009 Fall 12 10
1 2009 Spring 13 14
1 2009 Winter 27 20
2 2008 Fall 12 13
2 2008 Spring 13 11
2 2008 Winter 25 29
2 2009 Fall 16 23
2 2009 Spring 14 20
2 2009 Winter 21 26
3 2008 Fall 11 17
3 2008 Spring 12 12
3 2008 Winter 22 23
3 2009 Fall 13 14
3 2009 Spring 11 9
3 2009 Winter 27 31
Я безуспешно пытался использовать перекроить и таять. Существующие сообщения обращаются к преобразованию в результат одного столбца.
4 ответа:
Используя
reshape2
:# Thanks to Ista for helping with direct naming using "variable.name" df.m <- melt(df, id.var = c("ID", "Test", "Year"), variable.name = "Time") df.m <- transform(df.m, Test = paste0("Test", Test)) dcast(df.m, ID + Year + Time ~ Test, value.var = "value")
Обновление: использование данных.таблица расплав / отливка из версий >= 1.9.0:
data.table
из версий 1.9.0 импортирует пакетreshape2
и реализует быстрые методыmelt
иdcast
в C для данных.таблицы. Сравнение скорости на больших данных показано ниже.Для получения дополнительной информации о новостях, перейдите здесь.
require(data.table) ## ver. >=1.9.0 require(reshape2) dt <- as.data.table(df, key=c("ID", "Test", "Year")) dt.m <- melt(dt, id.var = c("ID", "Test", "Year"), variable.name = "Time") dt.m[, Test := paste0("Test", Test)] dcast.data.table(dt.m, ID + Year + Time ~ Test, value.var = "value")
На данный момент вам придется написать
dcast.data.table
явно, так как это не S3 generic вreshape2
пока.
Бенчмаркинг на больших данных:
# generate data: set.seed(45L) DT <- data.table(ID = sample(1e2, 1e7, TRUE), Test = sample(1e3, 1e7, TRUE), Year = sample(2008:2014, 1e7,TRUE), Fall = sample(50, 1e7, TRUE), Spring = sample(50, 1e7,TRUE), Winter = sample(50, 1e7, TRUE)) DF <- as.data.frame(DT)
Тайминги Reshape2:
reshape2_melt <- function(df) { df.m <- melt(df, id.var = c("ID", "Test", "Year"), variable.name = "Time") } # min. of three consecutive runs system.time(df.m <- reshape2_melt(DF)) # user system elapsed # 43.319 4.909 48.932 df.m <- transform(df.m, Test = paste0("Test", Test)) reshape2_cast <- function(df) { dcast(df.m, ID + Year + Time ~ Test, value.var = "value") } # min. of three consecutive runs system.time(reshape2_cast(df.m)) # user system elapsed # 57.728 9.712 69.573
Данные.таблица таймингов:
DT_melt <- function(dt) { dt.m <- melt(dt, id.var = c("ID", "Test", "Year"), variable.name = "Time") } # min. of three consecutive runs system.time(dt.m <- reshape2_melt(DT)) # user system elapsed # 0.276 0.001 0.279 dt.m[, Test := paste0("Test", Test)] DT_cast <- function(dt) { dcast.data.table(dt.m, ID + Year + Time ~ Test, value.var = "value") } # min. of three consecutive runs system.time(DT_cast(dt.m)) # user system elapsed # 12.732 0.825 14.006
melt.data.table
является ~175x быстрее , чемreshape2:::melt
иdcast.data.table
является ~5x, чемreshape2:::dcast
.
Базовый
reshape
альтернативный метод функции приведен ниже. Хотя для этого требуется использоватьreshape
дважды, может быть, есть более простой способ.Предполагая, что ваш набор данных называется
df1
tmp <- reshape(df1,idvar=c("ID","Year"),timevar="Test",direction="wide") result <- reshape( tmp, idvar=c("ID","Year"), varying=list(3:5,6:8), v.names=c("Test1","Test2"), times=c("Fall","Spring","Winter"), direction="long" )
Что дает:
> result ID Year time Test1 Test2 1.2008.Fall 1 2008 Fall 15 22 1.2009.Fall 1 2009 Fall 12 10 2.2008.Fall 2 2008 Fall 12 13 2.2009.Fall 2 2009 Fall 16 23 3.2008.Fall 3 2008 Fall 11 17 3.2009.Fall 3 2009 Fall 13 14 1.2008.Spring 1 2008 Spring 16 22 1.2009.Spring 1 2009 Spring 13 14 2.2008.Spring 2 2008 Spring 13 11 2.2009.Spring 2 2009 Spring 14 20 3.2008.Spring 3 2008 Spring 12 12 3.2009.Spring 3 2009 Spring 11 9 1.2008.Winter 1 2008 Winter 19 24 1.2009.Winter 1 2009 Winter 27 20 2.2008.Winter 2 2008 Winter 25 29 2.2009.Winter 2 2009 Winter 21 26 3.2008.Winter 3 2008 Winter 22 23 3.2009.Winter 3 2009 Winter 27 31
Придерживаясь базы R, это еще один хороший кандидат для "
stack
+reshape
" рутина. Предположим, что наш набор данных называется "mydf":mydf.temp <- data.frame(mydf[1:3], stack(mydf[4:6])) mydf2 <- reshape(mydf.temp, direction = "wide", idvar=c("ID", "Year", "ind"), timevar="Test") names(mydf2) <- c("ID", "Year", "Time", "Test1", "Test2") mydf2 # ID Year Time Test1 Test2 # 1 1 2008 Fall 15 22 # 2 1 2009 Fall 12 10 # 5 2 2008 Fall 12 13 # 6 2 2009 Fall 16 23 # 9 3 2008 Fall 11 17 # 10 3 2009 Fall 13 14 # 13 1 2008 Spring 16 22 # 14 1 2009 Spring 13 14 # 17 2 2008 Spring 13 11 # 18 2 2009 Spring 14 20 # 21 3 2008 Spring 12 12 # 22 3 2009 Spring 11 9 # 25 1 2008 Winter 19 24 # 26 1 2009 Winter 27 20 # 29 2 2008 Winter 25 29 # 30 2 2009 Winter 21 26 # 33 3 2008 Winter 22 23 # 34 3 2009 Winter 27 31