亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

正確/最快地重塑數據表的方法

正確/最快地重塑數據表的方法

慕妹3242003 2019-11-06 10:44:15
我在R中有一個數據表:library(data.table)set.seed(1234)DT <- data.table(x=rep(c(1,2,3),each=4), y=c("A","B"), v=sample(1:100,12))DT      x y  v [1,] 1 A 12 [2,] 1 B 62 [3,] 1 A 60 [4,] 1 B 61 [5,] 2 A 83 [6,] 2 B 97 [7,] 2 A  1 [8,] 2 B 22 [9,] 3 A 99[10,] 3 B 47[11,] 3 A 63[12,] 3 B 49我可以通過data.table中的組輕松地對變量v求和:out <- DT[,list(SUM=sum(v)),by=list(x,y)]out     x  y SUM[1,] 1 A  72[2,] 1 B 123[3,] 2 A  84[4,] 2 B 119[5,] 3 A 162[6,] 3 B  96但是,我想將組(y)作為列而不是行。我可以使用reshape以下方法完成此操作:out <- reshape(out,direction='wide',idvar='x', timevar='y')out     x SUM.A SUM.B[1,] 1    72   123[2,] 2    84   119[3,] 3   162    96有聚合之后重塑數據更有效的方法?是否有任何方法可以使用data.table操作將這些操作組合為一個步驟?
查看完整描述

3 回答

?
GCT1015

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?


查看完整回答
反對 回復 2019-11-06
?
隔江千里

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


查看完整回答
反對 回復 2019-11-06
  • 3 回答
  • 0 關注
  • 713 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號