【发布时间】:2016-04-14 00:48:54
【问题描述】:
这类似于 kdb 中快得多 (20 倍) 的 ungroup 函数。
我正在寻找一个类似(但速度更快)的函数,假设 data.table 包含多个列表列,每个列在每行上具有相同数量的元素,将扩展 data.table。
这是this post的扩展。
library(data.table)
library(tidyr)
t = Sys.time()
DT = data.table(a=c(1,2,3),
b=c('q','w','e'),
c=list(rep(t,2),rep(t+1,3),rep(t,0)),
d=list(rep(1,2),rep(20,3),rep(1,0)))
print(DT)
a b c d
1: 1 q 2016-01-09 09:55:14,2016-01-09 09:55:14 1,1
2: 2 w 2016-01-09 09:55:15,2016-01-09 09:55:15,2016-01-09 09:55:15 20,20,20
3: 3 e
print(unnest(DT))
Source: local data frame [5 x 4]
a b c d
(dbl) (chr) (time) (dbl)
1 1 q 2016-01-09 09:55:14 1
2 1 q 2016-01-09 09:55:14 1
3 2 w 2016-01-09 09:55:15 20
4 2 w 2016-01-09 09:55:15 20
5 2 w 2016-01-09 09:55:15 20
这是我自己的尝试……这似乎快了 2 倍,但应该大大改进……
dtUngroup <- function(DT){
colClasses <- lapply(DT,FUN=class)
listCols <- colnames(DT)[colClasses=='list']
if(length(listCols)>0){
nonListCols <- setdiff(colnames(DT),listCols)
nbListElem <- unlist(DT[,lapply(.SD,FUN=lengths),.SDcols=(listCols[1L])])
DT1 <- DT[,lapply(.SD,FUN=rep,times=(nbListElem)),.SDcols=(nonListCols)]
DT1[,(listCols):=DT[,lapply(.SD,FUN=function(x) do.call('c',x)),.SDcols=(listCols)]]
return(DT1)
}
return(DT)
}
dtUngroup(DT)[]
a b c d
1: 1 q 2016-01-09 09:55:14 1
2: 1 q 2016-01-09 09:55:14 1
3: 2 w 2016-01-09 09:55:15 20
4: 2 w 2016-01-09 09:55:15 20
5: 2 w 2016-01-09 09:55:15 20
【问题讨论】:
-
好吧,不要把 POSIXct 列出来……随意起草一个答案……
-
您可以使用以下命令使其更短:
DT[, lapply(.SD, unlist), by = 1:nrow(DT)] -
在
oce包中使用numberAsPOSIXct()和Jaap 的想法,下面可能是你所追求的:DT[, lapply(.SD, unlist), by = 1:nrow(DT)][, c := numberAsPOSIXct(c)][] -
为什么是这个而不是 FUN=function(x) do.call('c',x) ?我同意我可以节省 2 行...但它更快吗?
-
@jazzurro 只使用
asPOSIXct也可以
标签: r data.table kdb tidyr