【问题标题】:Vectorized vs non-vectorized for loop efficiency [closed]循环效率的矢量化与非矢量化[关闭]
【发布时间】:2021-03-01 17:06:32
【问题描述】:

我正在尝试编写一个简单的 for 循环,根据项目的新程度(在随机范围内)对数据框中的项目进行排名。

下面的代码运行良好,但根据我对 R 的理解(目前正在学习 R),这可能不是非常可扩展或使用 R 最强大的功能。它也可能需要更多的标准,进一步减慢它的速度

这是在数据框中循环遍历行的最佳方法吗?如果不是,我将如何对其进行矢量化?

我的数据是这样的,

   Product_ID  Product_Created Price_GBP shoprank       absdate
1          19 09/09/2010 04:38        50      135 3723.495 days
2          20 09/09/2010 04:44        50       19 3723.495 days
3          39 09/09/2010 04:58        50      117 3723.495 days
4          40 09/09/2010 05:03        50       68 3723.495 days
5       21957 15/10/2010 02:48      1250       21 3687.495 days
6           8 01/04/2011 17:50       149      137 3519.495 days
7           9 12/04/2011 18:18       120       55 3508.495 days
8        5647 25/04/2011 20:01       300       73 3495.495 days
9        1178 28/04/2011 10:09       450       55 3492.495 days
10         11 28/04/2011 15:32       410      141 3492.495 days

我是这样计算absdate的,

safeproducts$absdate <- difftime(Sys.time(), safeproducts$Product_Created,,units = ("days"))

还有我的 for 循环,

for (i in 1:nrow(safeproducts)){
  if (safeproducts$absdate[i] <= 30) {
    safeproducts$shoprank[i] <- sample(1:300,1)
  } else if (safeproducts$absdate[i] > 30 & safeproducts$absdate[i] <= 180){
    safeproducts$shoprank[i] <- sample(1:330,1)
  } else if (safeproducts$absdate[i] > 180) {
    safeproducts$shoprank[i] <- sample(1:150,1)
  }
}

正如我所提到的,我目前正在学习 R,因此非常感谢任何帮助

【问题讨论】:

  • 您能否将您的数据的可重现示例放入问题中?只需发布dput(safeproducts) 的输出即可。
  • 对了,你确定要在这里使用sample()吗?我想知道你的目标是什么。
  • 我正在尝试根据每个产品的年龄(以天为单位)在给定的时间间隔内给每个产品一个随机数,并计划用价格来执行此操作,以生成某种“排名”随机噪声

标签: r for-loop vectorization


【解决方案1】:

好的,我不知道你的循环应该做什么,但这里有一个使用 tidverse 包的更密集的版本。

library(tidyverse)

safeproducts %>%
    mutate(absdate_class = case_when(absdate <= 30 ~ 300
                                     , absdate <= 180 ~ 330
                                     , TRUE ~ 150)) %>%
    group_by(absdate_class) %>%
    mutate(shoprank = sample.int(first(absdate_class), n(), replace = TRUE)) %>%
    ungroup() %>%
    select(-absdate_class)

将管道符号(%&gt;%)读作“then”,如“取数据框”then“计算变量absdate_class”等等。阅读此book 会有很大帮助。

通常在for 循环上。尽可能在R 中避开它们。您想在 R 中使用 for 循环的唯一真实场景是循环的迭代 i 需要迭代 i-1 的结果。

快乐学习。 :)

【讨论】:

  • 可以把sample放在case_when里面,不需要group by等
  • 没那么重要,但我认为仅导入 dplyr 就足够了,而不是整个 tidyverse
  • case_when() 内部调用sample():确实如此。我没有运行代码,但我猜这在大数据集上会慢得多。假设您有一百万行,而不是调用 sample() 一百万次而不是 3 次。我的猜测是这会很慢。但就像我说的 - 没试过。
猜你喜欢
  • 2021-03-04
  • 2010-09-29
  • 2012-09-24
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 2011-11-26
  • 2020-10-02
  • 1970-01-01
相关资源
最近更新 更多