【问题标题】:Conversion from R data.table to nested list从 R data.table 转换为嵌套列表
【发布时间】:2016-08-29 16:43:22
【问题描述】:

假设我想从 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),
                        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)

为什么创建嵌套列表比创建数据表慢?有没有办法加快我的list_from_dt 功能?我假设对 my_dt 的查找相对较快,因为它是由 id 键入的。瓶颈是否来自为我的嵌套列表中的矩阵分配大量零碎的内存?

【问题讨论】:

  • 我的意思是,拆分 obj 并计算摘要统计信息很慢并不奇怪,是吗?创建单个对象也不是很快。您可能对lapply(split(...)) 感兴趣。 split.data.table 函数是高效的,并且在包的开发版本 (1.9.7) 上可用。
  • @Frank 谢谢你的指点,我会尝试让 data.table 1.9.7 工作(我有 1.9.6)。我对 list_from_dt 速度较慢并不感到惊讶,但我对慢了多少感到惊讶。它没有做太多的计算,只是复制数据。

标签: r performance list data.table


【解决方案1】:

这是我看到的splitgmax

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 值,现在用作列表元素的名称。

【讨论】:

    猜你喜欢
    • 2021-11-25
    • 1970-01-01
    • 2016-03-13
    • 2020-05-24
    • 2015-02-03
    • 2016-06-17
    • 1970-01-01
    • 2017-08-02
    • 2017-04-21
    相关资源
    最近更新 更多