【问题标题】:Trying to vectorize a for loop in R尝试矢量化 R 中的 for 循环
【发布时间】:2014-10-03 21:21:22
【问题描述】:

更新

感谢@CarlWitthoft 的帮助和建议,我的代码被简化为:

model <- unlist(sapply(1:length(model.list),
         function(i) ifelse(length(model.list[[i]][model.lookup[[i]]] == "") == 0,
                            NA, model.list[[i]][model.lookup[[i]]])))

原帖

最近我读到一篇文章,关于如何在 R 中进行矢量化操作而不是使用 for 循环是一种很好的做法,我有一段代码,我在其中使用了一个大的 for 循环,我正在尝试将其设为矢量操作,但我找不到答案,有人可以帮助我吗?有可能还是我需要改变我的方法?我的代码适用于 for 循环,但我想尝试另一种方式。

model <- c(0)
price <- c(0)
size <- c(0)
reviews <- c(0)
for(i in 1:length(model.list)) {
  if(length(model.list[[i]][model.lookup[[i]]] == "") == 0) {
    model[i] <- NA
  } else {
    model[i] <- model.list[[i]][model.lookup[[i]]]
  }
  if(length(model.list[[i]][price.lookup[[i]]] == "") == 0) {
    price[i] <- NA
  } else {
    price[i] <- model.list[[i]][price.lookup[[i]]]
  }
  if(length(model.list[[i]][reviews.lookup[[i]]] == "") == 0) {
    reviews[i] <- NA
  } else {
    reviews[i] <- model.list[[i]][reviews.lookup[[i]]]
  }
  size[i] <- product.link[[i]][size.lookup[[i]]]
}

基本上,model.list 变量是我要从中提取特定向量的列表,该向量的位置由变量 model.lookupprice.lookupreviews.lookup 给出,其中包含只有一个的逻辑向量TRUE 值,用于从 model.list 返回所需的向量。然后在for循环的每个循环中提取的向量存储在变量modelpricesizereviews中。

这个可以改成向量运算吗?

【问题讨论】:

  • 这个可以改成向量运算吗? - 是的 - 答案几乎总是肯定的。我怀疑如果你让你的问题独立且可重复,你会更幸运地获得足够的答案。

标签: r for-loop vector vectorization


【解决方案1】:

一般来说,在不需要的时候尽量避免if。我认为你想要的输出可以如下构建。

model <- unlist(sapply(1:length(model.list), function(i) model.list[[i]][model.lookup[[i]]]))
model[model=='']<-NA

其他变量也是如此。这假设所有model.lookup[[i]] 的长度都是1。如果不是,您首先将无法将输出写入model 的单个元素。

我还要注意到您严重过度编码,例如x&lt;-0x&lt;-c(0) 好,不要打扰 length 对单个项目的评估。

【讨论】:

  • 感谢您的回复和建议。您的代码运行良好,但有一些细节。我如何在你的函数中替换我的这部分代码? if(length(model.list[[i]][model.lookup[[i]]] == "") == 0) { model[i]
  • 我不确定你在问什么。您的代码有一个 "if / else" ,因此 model[i] 的每个元素都被分配了一个值或 NA。我的代码首先将值直接分配给所有 model[i] ,然后将 "" 值替换为 NA 。如果您收到计数错误,则不是由于 sapply 造成的。您能否仔细检查子列表 model.list[[i]][model.lookup] 的长度以确保它们都具有第 i 个元素?也就是说,每个 model.lookup 子列表至少与 model.list 的元素数一样长。
  • 我后来根据您的代码添加的 ifelse 函数,现在它工作得很好!我的代码是这样结束的:lookup &lt;- function(i, arg1, arg2) { return(ifelse(length(arg1[[i]][arg2[[i]]]) == 0, NA, arg1[[i]][arg2[[i]]])) }; model &lt;- unlist(sapply(1:length(model.list), function(i) lookup(i, model.list, model.lookup))) 抱歉,我不知道如何编辑响应 cmets。
猜你喜欢
  • 2020-05-03
  • 1970-01-01
  • 2019-02-28
  • 2012-12-10
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
相关资源
最近更新 更多