【问题标题】:Growing a list with variable names in R在 R 中用变量名增长一个列表
【发布时间】:2013-01-25 21:34:46
【问题描述】:

我正在尝试在 R 中增加一个列表,其中每个条目的值和名称都保存在一个变量中,但它似乎不起作用。

my_models_names <- names(my_models)
my_rocs=list() 
for (modl in my_models_names) {

    my_probs <- testPred[[modl]]$Y1
    my_roc <- roc(Ytst, my_probs)
    c(my_rocs, modl=my_roc) # <-- modl and my_roc are both variables
    }

我的列表my_rocs 最后是空的,即使我知道循环会迭代(my_roc 已填写)为什么?

在相关说明中,有没有办法在不循环的情况下做到这一点?

【问题讨论】:

  • 请重现示例... ?? tinyurl.com/reproducible-000 ... lapply 是在没有(显式)循环的情况下解决问题的方法
  • 谢谢@BenBolker。你是对的,很抱歉没有提供它,我会把它放在一起,但同时我想我在另一个线程上找到了答案。

标签: r list


【解决方案1】:

通常在 R 中,不断增长的对象是不好的。与从完整对象开始并填充它相比,它增加了使用的内存量。看来您提前知道列表的大小应该是多少。

例如:

my_keys <- letters[1:3]
mylist <- vector(mode="list", length=length(my_keys))
names(mylist) <- my_keys

mylist
## $a
## NULL

## $b
## NULL

## $c
## NULL

你可以这样分配:

key <- "a"
mylist[[key]] <- 5
mylist
## $a
## [1] 5
##
## $b
## NULL
##
## $c
## NULL

【讨论】:

  • +1。更重要的是内存使用,内存的不断重新分配使得大型数据集的对象增长非常缓慢,高达几个数量级。
  • 增长列表很好,事实上:r-bloggers.com/growing-list-vs-growing-queue
  • @PaulHiemstra ,对于当前 R 实现的列表来说,这似乎不是问题。 system.time({ l = list(); for(i in 1:5000) l[[i]] = rnorm(1E4)});system.time({l = lapply(1:5000, function(i) rnorm(1E4))})
  • 我一般都遵循“生长对象不好”的建议;但我必须说我真的不明白它对列表有什么影响。我可以有一个长度为 4 的列表占用我的整个内存,而长度为 100 的列表只占用一小部分。列表的长度并不能说明它的大小。
【解决方案2】:

我在this thread找到了答案。

我可以使用以下通用公式扩展列表:

mylist <- list()

for (key in my_keys){ 
mylist[[ key ]] <- value # value is computed dynamically
}

在我的 OP 中:

  • mylistmy_rocs
  • keymodl
  • valuemy_roc

【讨论】:

  • 我真的会考虑不增长对象,当mylist 变大时,这会变得非常慢。请参阅我的答案以获取使用 lapply 的示例(这是 R 方法),或者将您的 mylist 预先分配到正确的大小。 mylist 很短时可能没有什么区别,但总的来说这种风格很慢。
  • 如果您需要使用 lapply() 为每个键创建多个列表,可以这样做吗? @PaulHiemstra
  • 增长列表似乎和 lapply system.time({l = lapply(letters, function(i) rnorm(1E6));names(l)=letters;force(l)}) 一样快system.time({ l = list(); for(i in letters) l[[i]] = rnorm(1E6);force(l)})
【解决方案3】:

您还可以使用更类似于 R 的解决方案,并使用 lapply

get_model = function(model_name) {
    my_probs <- testPred[[model_name]]$Y1
    return(roc(Ytst, my_probs))
  }
model_list = lapply(names(my_models), get_model)

请注意,此解决方案为您节省了大量样板代码,它也不会因增加对象而遭受解决方案的重新分配问题。对于大型数据集,这可能意味着lapply 解决方案的速度要快数千倍。

【讨论】:

  • lapply 是如何实现这一千倍的速度提升的?它不可能事先知道它所应用的函数每次迭代的输出大小?
猜你喜欢
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2021-03-02
  • 1970-01-01
相关资源
最近更新 更多