Перебор списка параметров с использованием тидикванта R
У меня есть набор данных, который я хочу обработать с использованием 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
Спасибо за помощь. Долгое время скрывался, впервые постер.
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