【问题标题】:Iterating through a list of parameters using tidyquant R使用 tidyquant R 遍历参数列表
【发布时间】:2018-11-25 23:31:44
【问题描述】:

我有一个数据集,我想使用 tq_mutate 和 rollapply 处理不同的参数值。

目前我正在使用 for 循环遍历所有参数值,但我确信这不是完成此任务的最有效或最快的方法(尤其是当我要查看大量参数时值)。如何改进或删除 for 循环?我怀疑这意味着使用 purrr::map 或其他方式(多线程/多核等),但我无法在网上找到有用的示例。

下面是一些示例代码。请忽略数据集和比例函数输出的简单性,仅用于说明目的。我想要做的是迭代许多不同的 V0 值。

library(dplyr)
library(tidyverse)
library(broom)
library(tidyquant)

my_bogus_function <- function(df, V0=1925) { 
  # WILL HAVE SOMETHING MORE SOPHISTICATED IN HERE BUT KEEPING IT SIMPLE
  # FOR THE PURPOSES OF THE QUESTION
  c(V0, V0*2)
}

window_size <- 7 * 24
cnames = c("foo", "bar")
df <- c("FB") %>%
    tq_get(get = "stock.prices", from = "2016-01-01", to = "2017-01-01") %>% 
    dplyr::select("date", "open")

# CAN THIS LOOP BE DONE IN A MORE EFFICIENT MANNER? 
for (i in (1825:1830)){
  df <- df %>% 
        tq_mutate(mutate_fun = rollapply,
                  width      = window_size,
                  by.column  = FALSE,
                  FUN        = my_bogus_function,
                  col_rename = gsub("$", sprintf(".%d", i), cnames), 
                  V0 = i
    )
}
# END OF THE FOR LOOP I WANT FASTER

【问题讨论】:

  • 关闭投票原因:错误:could not find function "tq_get"。要求我们追踪缺失的函数是不合理的。
  • 如果您安装了“tidyquant”库中的“tq_get”函数,您应该可以使用它。我只是将它用于虚拟数据。问题实际上是关于迭代值列表的更有效方法。
  • 即使在执行 install.packages("tidyquant") 之后,问题仍然不清楚。您尚未指定结果的不当之处:names(df) 返回 ` [1] "date" "open" "foo.1825" "bar.1825" "foo.1826" "bar.1826" "foo.1827" “bar.1827” “foo.1828” “bar.1828” [11] “foo.1829” “bar.1829” “foo.1830” “bar.1830”`。所以我不能改变我的密切投票背后的原因,但我也不会改变它。
  • 道歉,应该添加到“目前我正在使用 for 循环来检查所有参数,但我确信这不是完成这项任务的最有效方法。” “我想使用“地图”或其他更快的方法来做到这一点”。编辑问题以使其更清晰。
  • For 循环并不比其他迭代方法慢,尽管您可能会在不了解 R 的人编写的网页上遇到任何错误信息。

标签: r dplyr rstudio purrr tidyquant


【解决方案1】:

鉴于 R 使用一个核心,我发现通过使用允许使用多个核心的并行包、doSNOW 和 foreach 得到了改进(请注意,我在 Windows 机器上,因此其他一些包不可用)。

我确信对于多线程/并行/向量化代码还有其他答案。

这里是任何感兴趣的人的代码。

library(dplyr)
library(tidyverse)
library(tidyquant)
library(parallel)
library(doSNOW)  
library(foreach)

window_size <- 7 * 24
cnames = c("foo", "bar")
df <- c("FB") %>%
  tq_get(get = "stock.prices", from = "2016-01-01", to = "2017-01-01") %>% 
  dplyr::select("date", "open")

my_bogus_function <- function(df, V0=1925) { 
  # WILL HAVE SOMETHING MORE SOPHISTICATED IN HERE BUT KEEPING IT SIMPLE
  # FOR THE PURPOSES OF THE QUESTION
  c(V0, V0*2)
}

# CAN THIS LOOP BE DONE IN A MORE EFFICIENT/FASTER MANNER? YES 
numCores <- detectCores() # get the number of cores available
cl <- makeCluster(numCores, type = "SOCK")
registerDoSNOW(cl) 

# Function to combine the outputs 
mycombinefunc <-  function(a,b){merge(a, b, by = c("date","open"))}

# Run the loop over multiple cores
meh <- foreach(i = 1825:1830, .combine = "mycombinefunc") %dopar% {
  message(i)
  df %>% 
    # Adjust everything
    tq_mutate(mutate_fun = rollapply,
              width      = window_size,
              by.column  = FALSE,
              FUN        = my_bogus_function,
              col_rename = gsub("$", sprintf(".%d", i), cnames), 
              V0 = i
    )
}
stopCluster(cl)
# END OF THE FOR LOOP I WANTED FASTER

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-19
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 2021-11-19
    • 1970-01-01
    相关资源
    最近更新 更多