Ускорить применение функции «cummean» к 4 векторам

#r #optimization #dplyr

#r #оптимизация #dplyr

Вопрос:

У меня есть 2 вектора одинаковой длины x,y . Тогда x^2,y^2 являются квадратными (поэлементно) x,y соответственно. На каждой итерации мне нужно применить функцию cummean on x,y,x^2,y^2 .

Я хотел бы спросить, могу ли я каким-то образом ускорить процесс, а не выполнять 4 отдельные операции.

 library(dplyr)
x <- c(1, 2, 3)
y <- c(5, 5, 6)

dplyr::cummean(x)
dplyr::cummean(y)
dplyr::cummean(x^2)
dplyr::cummean(y^2)
  

Большое спасибо за ваше предложение!

Комментарии:

1. Я не думаю, что имеется достаточно общей информации, чтобы предложить ускорение. Это зависит от того, как вы используете их в своем коде. Это 4 независимые операции. Вы могли бы сократить строку кода, используя lapply i.e lapply(list(x, y), function(x) list(cummean(x), cummean(x^2))) , но это не дает увеличения скорости.

2. Я тестировал в Rcpp, но dplyr ::cummean уже работает очень быстро, поэтому никаких улучшений. Обязательно обновитесь до версии dplyr v1.0.2, потому что в dplyr v1.0.0 была ошибка с cummean

Ответ №1:

Я думаю, вы могли бы сделать что-то вроде:

 tibble(x, y) %>% 
   mutate(across(1:2, ~.x^2, .names = c("{col}^2"))) %>% 
   mutate(across(1:4, cummean, .names = "cummean_{col}"))
#> # A tibble: 3 x 8
#>       x     y `x^2` `y^2` cummean_x cummean_y `cummean_x^2` `cummean_y^2`
#>   <dbl> <dbl> <dbl> <dbl>     <dbl>     <dbl>         <dbl>         <dbl>
#> 1     1     5     1    25      1            5             1            25
#> 2     2     5     4    25      1            5             1            25
#> 3     3     6     9    36      1.33         5             2            25
  

И если вы хотите, чтобы переменные находились в глобальной среде, а не в tibble, вы могли бы сделать:

 tibble(x, y) %>% 
  mutate(across(1:2, ~.x^2, .names = c("{col}^2"))) %>% 
  mutate(across(1:4, cummean, .names = "cummean_{col}")) %>% 
  as.list() %>% 
  list2env(envir = globalenv())
  

Или в функции, если вам приходилось часто это делать, вы могли бы сделать:

 func <- function(x, y)
{
  tibble(x, y) %>% 
    mutate(across(1:2, ~.x^2, .names = c("{col}^2"))) %>% 
    mutate(across(1:4, cummean, .names = "cummean_{col}")) %>% 
    as.list() %>% 
    list2env(envir = parent.frame())
}
  

Комментарии:

1. к сожалению microbenchmark , по сравнению с 4 отдельными операциями чрезвычайно медленно

2. @Waldi Я предположил, что OP означает «избегать повторения кодирования», а не «улучшать скорость обработки», поскольку они сказали «вместо выполнения 4 отдельных операций». Однако я могу ошибаться в этом. Что касается скорости обработки raw, я предполагаю, что вы не сможете значительно улучшить cummean — вот почему еще одна причина, по которой я предполагаю, что OP искал код, который предотвращал повторение, а не ускорение. Разъяснение помогло бы. Спасибо за тестирование @Waldi

3. спасибо за ваш отзыв: давайте дождемся разъяснений от OP о том, как понять вопрос! И вы правы, cummean кажется непревзойденным по скорости.

4. Я имел в виду код для увеличения скорости моего алгоритма. Таким образом, @Waldi прав.