3 回答

TA貢獻1827條經驗 獲得超4個贊
該data.table軟件包實現了更快的melt/dcast功能(用C語言編寫)。通過允許熔化和澆鑄多列,它還具有其他功能。請在Github上使用data.tables查看新的高效重塑。
從v1.9.0版本開始提供data.table的melt / dcast功能,其功能包括:
reshape2鑄造前無需裝載包裝。但是,如果您希望將其加載用于其他操作,請在加載之前加載它data.table。
dcast也是S3的通用名稱。沒有了dcast.data.table()。只需使用dcast()。
melt:
能夠融化“列表”類型的列。
獲得variable.factor和value.factor,默認情況下分別為和,以TRUE與FALSE兼容reshape2。這樣可以直接控制variable和value列的輸出類型(是否為因子)。
melt.data.table的na.rm = TRUE參數經過內部優化,可在熔化過程中直接去除NA,因此效率更高。
新增:melt可以接受列表,列表measure.vars中每個元素中指定的列將合并在一起。通過使用進一步簡化了此過程patterns()。
dcast:
接受多個fun.aggregate和多個 value.var。
rowid()直接在公式中使用函數來生成ID列,有時需要ID來唯一地標識行。
舊基準:
melt :1000萬行和5列,從61.3秒減少到1.2秒。
dcast :1百萬行4列,從192秒減少到3.6秒。
科隆提醒(2013年12月)演示幻燈片32:為什么不向提交dcast拉取請求reshape2?

TA貢獻1906條經驗 獲得超10個贊
現在可以在data.table中實現此功能(從版本1.8.11開始)。
所以我想有一個data.table解決方案。應用于此問題:
library(data.table)
set.seed(1234)
DT <- data.table(x=rep(c(1,2,3),each=1e6),?
? ? ? ? ? ? ? ? ? y=c("A","B"),?
? ? ? ? ? ? ? ? ? v=sample(1:100,12))
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
# edit (mnel) to avoid setNames which creates a copy
# when calling `names<-` inside the function
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]
})
? ?x? ? ? ? A? ? ? ? B
1: 1 26499966 28166677
2: 2 26499978 28166673
3: 3 26500056 28166650
這與DWin的方法具有相同的結果:
tapply(DT$v,list(DT$x, DT$y), FUN=sum)
? ? ? ? ?A? ? ? ? B
1 26499966 28166677
2 26499978 28166673
3 26500056 28166650
而且,它很快:
system.time({?
? ?out <- DT[,list(SUM=sum(v)),by=list(x,y)]
? ?out[, as.list(setattr(SUM, 'names', y)), by=list(x)]})
##? user? system elapsed?
## 0.64? ? 0.05? ? 0.70?
system.time(tapply(DT$v,list(DT$x, DT$y), FUN=sum))
## user? system elapsed?
## 7.23? ? 0.16? ? 7.39?
更新
為了使該解決方案也適用于非平衡數據集(即某些組合不存在),您必須首先在數據表中輸入這些組合:
library(data.table)
set.seed(1234)
DT <- data.table(x=c(rep(c(1,2,3),each=4),3,4), y=c("A","B"), v=sample(1:100,14))
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
setkey(out, x, y)
intDT <- expand.grid(unique(out[,x]), unique(out[,y]))
setnames(intDT, c("x", "y"))
out <- out[intDT]
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]
摘要
結合上面的評論,這是一線解決方案:
DT[, sum(v), keyby = list(x,y)][CJ(unique(x), unique(y)), allow.cartesian = T][,
? ?setNames(as.list(V1), paste(y)), by = x]
也可以很容易地修改它,使其不僅具有總和,例如:
DT[, list(sum(v), mean(v)), keyby = list(x,y)][CJ(unique(x), unique(y)), allow.cartesian = T][,
? ?setNames(as.list(c(V1, V2)), c(paste0(y,".sum"), paste0(y,".mean"))), by = x]
#? ?x A.sum B.sum? ?A.mean B.mean
#1: 1? ? 72? ?123 36.00000? ?61.5
#2: 2? ? 84? ?119 42.00000? ?59.5
#3: 3? ?187? ? 96 62.33333? ?48.0
#4: 4? ? NA? ? 81? ? ? ?NA? ?81.0
- 3 回答
- 0 關注
- 713 瀏覽
添加回答
舉報