2013-08-19 4 views
2

Допустим, у меня есть data.table с этими столбцамиR data.table перекроить куски колонн сразу

nodeID 
hour1aaa 
hour1bbb 
hour1ccc 
hour2aaa 
hour2bbb 
hour2ccc 
... 
hour24aaa 
hour24bbb 
hour24ccc 

в общей сложности 72 колонн. Давайте назовем это rawtable

Я хочу, чтобы изменить его так, у меня есть

nodeID 
hour 
aaa 
bbb 
ccc 

в общей сложности только эти 5 столбцов где час колонка будет содержать какой бы час от первоначального 72, что должно быть. Давайте назовем это newshape

Как я это делаю сейчас, чтобы использовать rbindlist с 24 элементов, где каждый элемент является подмножеством большей data.table. Как это (за исключением я уезжаю из большинства часов в моем примере)

newshape<-rbindlist(list(
rawtable[,list(nodeID, Hour=1, aaa=hour1aaa, bbb=hour1bbb, ccc=hour1ccc)], 
rawtable[,list(nodeID, Hour=2, aaa=hour2aaa, bbb=hour2bbb, ccc=hour2ccc)], 
rawtable[,list(nodeID, Hour=24, aaa=hour24aaa, bbb=hour24bbb, ccc=hour24ccc)])) 

Вот некоторые выборочные данные, чтобы играть с

rawtable<-data.table(nodeID=c(1,2),hour1aaa=c(12.4,32),hour1bbb=c(61.1,65.33),hour1ccc=c(-4.2,54),hour2aaa=c(12.2,1.2),hour2bbb=c(12.2,5.7),hour2ccc=c(5.6,101.9),hour24aaa=c(45.2,8.5),hour24bbb=c(23,7.9),hour24ccc=c(98,32.3)) 

Используя мой rbindlist подход дает желаемый результат, но, как с большинством вещей, которые я делаю с R, возможно, лучший способ. К лучшему я имею в виду более эффективную память, быстрее и/или использует меньше строк кода. У кого-то есть лучший способ добиться этого?

ответ

3

Это классическая reshape проблема, если вы получите ваши имена в стандартной конвенции он ожидает, хотя я не уверен, что это на самом деле использует эффективность data.table структуры:

reshape(
    setNames(rawtable, gsub("(\\D+)(\\d+)(\\D+)", "\\3.\\2", names(rawtable))), 
    idvar="nodeID", direction="long", varying=-1 
) 

Результат:

nodeID hour aaa bbb ccc 
1:  1 1 12.4 61.10 -4.2 
2:  2 1 32.0 65.33 54.0 
3:  1 2 12.2 12.20 5.6 
4:  2 2 1.2 5.70 101.9 
5:  1 24 45.2 23.00 98.0 
6:  2 24 8.5 7.90 32.3 

@Arun ответ здесь: https://stackoverflow.com/a/15510828/496803 также может быть полезен, если вы можете приспособить его к вашим текущим данным.

+0

+1 Я не думаю, что возникла проблема с базой R reshape. Мне всегда кажется, что 'reshape' не беспокоится о том, чтобы выяснить часть' variableing = list (...) ', особенно когда вам нужно указывать' v.names' в этих случаях. – A5C1D2H2I1M1N2O1R2T1

+0

@ АнандаМахто - небольшая цена для оплаты, я полагаю. Вы всегда можете использовать 'keynames <- c (" aaa "," bbb "," ccc ")' и использовать 'lapply (keynames, grep, names (rawtable))' в 'изменяющихся' и' keynames' в ' часть v.names'. Однако это немного неудобно. – thelatemail

+0

Я определил для своих целей векторы «grep» для таких целей: 'vGrep <- Vectorize (grep,« pattern », SIMPLIFY = FALSE)'. – A5C1D2H2I1M1N2O1R2T1

2

Один из вариантов - использовать merged.stack из моего пакета «splitstackshape». Эта функция, stack s групп столбцов, а затем объединяет результаты вместе. Из-за того, как функция создает переменную «время», вы можете указать, что вы хотели бы удалить из имен столбцов. В этом случае мы хотим вырезать «час», «aaa», «bbb» и «ccc» и иметь только оставшиеся цифры.

library(splitstackshape) 
## Make sure you're using at least 1.2.0 
packageVersion("splitstackshape") 
# [1] ‘1.2.0’ 
merged.stack(rawtable, id.vars="nodeID", 
      var.stubs=c("aaa", "bbb", "ccc"), 
      sep="hour|aaa|bbb|ccc") 
# nodeID .time_1 aaa bbb ccc 
# 1:  1  1 12.4 61.10 -4.2 
# 2:  1  2 12.2 12.20 5.6 
# 3:  1  24 45.2 23.00 98.0 
# 4:  2  1 32.0 65.33 54.0 
# 5:  2  2 1.2 5.70 101.9 
# 6:  2  24 8.5 7.90 32.3 
Смежные вопросы