Расчет вложенной суммы - PullRequest
       8

Расчет вложенной суммы

0 голосов
/ 22 декабря 2019

Я хотел бы вычислить в R что-то следующего вида:

formular

Важно, чтобы слагаемое могло быть любой функцией f (y, x).

Мой подход до сих пор заключается в использовании вложенных циклов:

n <- 5
fun <- function(y,x){y^2 + sqrt(y*x)} # might be any function of y and x
sum_x <- c()
for(x in 1:n){
  sum_y <- c()
  for(y in 0:x){
    sum_y[y+1] <- fun(y,x)
  }
  sum_x[x] <- sum(sum_y)
}
sum(sum_x) # 147.6317

Однако этот подход мне не нравится. Это довольно уродливо и становится очень неудобно, если нижняя и верхняя границы должны быть более гибкими. Я думал об использовании expand.grid, а затем о применении fun к нему с помощью mapply, но не мог понять, как выразить вложенную структуру сумм. Любые предложения, как это сделать?

Ответы [ 3 ]

2 голосов
/ 22 декабря 2019

Вы можете выполнить произведение outer на основе функции. Этот внешний продукт будет смотреть на все комбинации двух входных переменных и помещать результат в матрицу;он принимает следующую форму:

outer(<rows>, <cols>, FUN)

В вашем конкретном случае достаточно:

n <- 5

fun <- function(x, y) {ifelse (y > x, 0, y^2 + sqrt(x * y))}

outer(1:n, 1:n, FUN = fun) %>% sum() # 147.6317

, поскольку y варьируется от 0 и y встречается в обоих терминах, по умолчанию 0 (случайно). Несмотря на это, в этом случае необходимо включить некоторую форму индексации в определение функции, поскольку вложенное суммирование y зависит от x.

1 голос
/ 22 декабря 2019

Вы можете использовать вложенный sapply, который будет применяться fun только для требуемых условий, а затем взять sum его.

sum(unlist(sapply(seq_len(n), function(x) sapply(0:x, fun, x))))
#[1] 147.6317
1 голос
/ 22 декабря 2019

Мы также можем использовать outer с использованием rowCumsums с matrixStats

library(matrixStats)
sum(outer(seq_len(n), seq_len(n), FUN = fun) * rowCumsums(diag(n)))
#[1] 147.6317

Или с crossing с tidyr

library(tidyr)
library(dplyr)
crossing(x = seq_len(n), y = seq_len(n)) %>%
   filter(y <= x) %>%
   transmute(out = fun(y, x)) %>%
   summarise(out = sum(out)) %>% 
   pull(out)
#[1] 147.6317
...