从R data.table到嵌套列表的转换
假设我想从R data.table创建一个嵌套列表,如下例所示:从R data.table到嵌套列表的转换,r,performance,list,data.table,R,Performance,List,Data.table,假设我想从R data.table创建一个嵌套列表,如下例所示: library(data.table) generate_dt <- function(num_unique_id=100, rows_per_id=2) { num_rows <- num_unique_id * rows_per_id my_dt <- data.table(my_id=rep(seq(1, num_unique_id), rows_per_id),
library(data.table)
generate_dt <- function(num_unique_id=100, rows_per_id=2) {
num_rows <- num_unique_id * rows_per_id
my_dt <- data.table(my_id=rep(seq(1, num_unique_id), rows_per_id),
y1=rnorm(num_rows), y2=rnorm(num_rows), y3=rnorm(num_rows),
z=runif(num_rows))
setkey(my_dt, my_id)
return(my_dt)
}
## Suppose I want to go from my_dt to a nested list
list_from_dt <- function(my_dt) {
num_unique_id <- length(unique(my_dt$my_id))
my_list <- lapply(seq_len(num_unique_id), function(id) {
my_dt_subset <- my_dt[J(id)]
return(list(y=as.matrix(my_dt_subset[, c("y1", "y2", "y3"), with=FALSE]),
max_z=max(my_dt_subset$z)))
})
stopifnot(is.matrix(my_list[[1]]$y))
return(my_list)
}
my_dt <- generate_dt()
my_list <- list_from_dt(my_dt) # Suppose I have some code that expects a nested list like this
system.time(replicate(100, unused <- generate_dt())) # Fast, 0.062 elapsed
system.time(replicate(100, unused <- list_from_dt(my_dt))) # Roughly 200 times slower (12.586 elapsed)
库(data.table)
生成\u dt以下是我在split
和gmax
中看到的内容:
f = function(){
s = lapply(split(my_dt[, !"z", with=FALSE], by="my_id", keep.by=FALSE), as.matrix)
mz = my_dt[, max(z), by=my_id]
Map(list, ys = s, mz = mz$V1)
}
system.time(replicate(100, generate_dt())) # 0.1
system.time(replicate(100, list_from_dt(my_dt))) # 20.1
system.time(replicate(100, f())) # 2.1
看起来是这样的:
> head(res, 2)
$`1`
$`1`$ys
y1 y2 y3
[1,] -0.04493979 -1.01340856 0.08481358
[2,] -0.75860610 0.04113645 -0.36270441
$`1`$mz
[1] 0.9362695
$`2`
$`2`$ys
y1 y2 y3
[1,] 0.7718361 -0.8005803 1.2195464
[2,] 0.1658420 -1.2846028 0.4607024
$`2`$mz
[1] 0.8551927
数字,`1`
和`2`
是我的id
值,现在用作列表元素的名称。以下是我在拆分
和gmax
中看到的内容:
f = function(){
s = lapply(split(my_dt[, !"z", with=FALSE], by="my_id", keep.by=FALSE), as.matrix)
mz = my_dt[, max(z), by=my_id]
Map(list, ys = s, mz = mz$V1)
}
system.time(replicate(100, generate_dt())) # 0.1
system.time(replicate(100, list_from_dt(my_dt))) # 20.1
system.time(replicate(100, f())) # 2.1
看起来是这样的:
> head(res, 2)
$`1`
$`1`$ys
y1 y2 y3
[1,] -0.04493979 -1.01340856 0.08481358
[2,] -0.75860610 0.04113645 -0.36270441
$`1`$mz
[1] 0.9362695
$`2`
$`2`$ys
y1 y2 y3
[1,] 0.7718361 -0.8005803 1.2195464
[2,] 0.1658420 -1.2846028 0.4607024
$`2`$mz
[1] 0.8551927
数字,`1`
和`2`
是my_id
值,现在用作列表元素的名称。我的意思是,将obj拆分并计算摘要统计数据的速度很慢并不奇怪,不是吗?也不是说创建单个对象很快。您可能对lappy(split(…)
感兴趣。split.data.table
函数非常有效,可以在软件包的devel版本(1.9.7)上使用。@Frank谢谢你的指针,我会尝试让data.table 1.9.7正常工作(我有1.9.6)。我并不感到惊讶的是,来自_dt的列表_速度较慢,但我感到惊讶的是,它的速度要慢得多。它没有做太多的计算,只是复制数据。我的意思是,将obj拆分并计算摘要统计数据的速度很慢,这并不奇怪,不是吗?也不是说创建单个对象很快。您可能对lappy(split(…)
感兴趣。split.data.table
函数非常有效,可以在软件包的devel版本(1.9.7)上使用。@Frank谢谢你的指针,我会尝试让data.table 1.9.7正常工作(我有1.9.6)。我并不感到惊讶的是,来自_dt的列表_速度较慢,但我感到惊讶的是,它的速度要慢得多。它没有做太多的计算,只是复制数据。