Introdução

Este relatório tem como objetivo implementar e comparar funções recursivas para calcular a média móvel exponencialmente ponderada (EWMA) e coeficientes binomiais. Além disso, vamos comparar o desempenho dessas funções com abordagens iterativas e funções já existentes no R.

Suavização Exponencial (EWMA)

Yi=λXi+(1−λ)Y(i−1)

A média móvel exponencialmente ponderada (EWMA) é uma técnica de suavização que aplica pesos decrescentes exponencialmente às observações passadas. A equação de recorrência para EWMA é dada por:

Implementação Recursiva da EWMA

# Função recursiva para calcular a EWMA
ewma_recursive <- function(x, lambda, y_prev = NULL) {
  if (is.null(y_prev)) {
    y_prev <- x[1]  # Condição inicial
  }
  if (length(x) == 0) {
    return(numeric(0))  # Condição de parada
  }
  y <- lambda * x[1] + (1 - lambda) * y_prev
  return(c(y, ewma_recursive(x[-1], lambda, y)))
}

# Carregando os dados
dados <- c(100.23, 100.19, 102.02, 99.59, 99.81, 99.86, 99.60, 100.35, 99.38, 100.83,
           99.73, 98.00, 99.72, 101.34, 98.77, 99.94, 99.47, 99.95, 100.33, 99.57,
           100.82, 100.23, 100.68, 101.64, 100.86, 99.28, 101.41, 100.21, 101.85, 101.43, 103.00)

# Aplicando a função recursiva
lambda <- 0.2
resultado_recursivo <- ewma_recursive(dados, lambda)
print(resultado_recursivo)
##  [1] 100.23000 100.22200 100.58160 100.38328 100.26862 100.18690 100.06952
##  [8] 100.12562  99.97649 100.14719 100.06376  99.65100  99.66480  99.99984
## [15]  99.75387  99.79110  99.72688  99.77150  99.88320  99.82056 100.02045
## [22] 100.06236 100.18589 100.47671 100.55337 100.29869 100.52096 100.45876
## [29] 100.73701 100.87561 101.30049

Comparação com Abordagem Iterativa

# Função iterativa para calcular a EWMA
ewma_iterative <- function(x, lambda) {
  y <- numeric(length(x))
  y[1] <- x[1]
  for (i in 2:length(x)) {
    y[i] <- lambda * x[i] + (1 - lambda) * y[i - 1]
  }
  return(y)
}

# Aplicando a função iterativa
resultado_iterativo <- ewma_iterative(dados, lambda)
print(resultado_iterativo)
##  [1] 100.23000 100.22200 100.58160 100.38328 100.26862 100.18690 100.06952
##  [8] 100.12562  99.97649 100.14719 100.06376  99.65100  99.66480  99.99984
## [15]  99.75387  99.79110  99.72688  99.77150  99.88320  99.82056 100.02045
## [22] 100.06236 100.18589 100.47671 100.55337 100.29869 100.52096 100.45876
## [29] 100.73701 100.87561 101.30049
# Comparação de desempenho

# Mede tempo de execução da função recursiva
tempo_recursivo <- system.time({
  for (i in 1:1000) {
    ewma_recursive(dados, lambda)
  }
})

# Mede tempo de execução da função iterativa
tempo_iterativo <- system.time({
  for (i in 1:1000) {
    ewma_iterative(dados, lambda)
  }
})

# Exibir os tempos
print(tempo_recursivo)
##    user  system elapsed 
##    0.09    0.01    0.11
print(tempo_iterativo)
##    user  system elapsed 
##       0       0       0

Comentários sobre o Desempenho

A abordagem recursiva pode ser mais elegante, mas em R, a recursão pode ser menos eficiente em termos de desempenho e memória, especialmente para grandes conjuntos de dados. A abordagem iterativa geralmente é mais eficiente em termos de tempo de execução.

Coeficientes Binomiais

Os coeficientes binomiais podem ser calculados usando a relação de recorrência

# Função recursiva para coeficientes binomiais
coef_binomial_recursivo <- function(n, k) {
  if (k == 0 || k == n) {
    return(1)  # Condições de parada
  }
  return(coef_binomial_recursivo(n - 1, k - 1) + coef_binomial_recursivo(n - 1, k))
}

# Exemplo de uso
n <- 5
k <- 2
resultado_recursivo <- coef_binomial_recursivo(n, k)
print(resultado_recursivo) 
## [1] 10
# Usando a função choose()
resultado_choose <- choose(n, k)

# Função vetorizada para coeficientes binomiais
coef_binomial_vetorizado <- function(n, k) {
  if (k == 0 || k == n) {
    return(1)
  }
  numerador <- prod((n - (k - 1)):n)  # n * (n-1) * ... * (n-k+1)
  denominador <- factorial(k)          # k!
  return(numerador / denominador)
}

# Exemplo de uso da abordagem vetorizada
resultado_vetorizado <- coef_binomial_vetorizado(n, k)

Comparação com a Função choose() e Abordagem Vetorizada

# Comparando os resultados
comparison_binomial <- data.frame(
  Recursive = resultado_recursivo,
  Choose = resultado_choose,
  Vectorized = resultado_vetorizado
)
print(comparison_binomial)
##   Recursive Choose Vectorized
## 1        10     10         10
# Mede tempo de execução da função recursiva
tempo_recursivo <- system.time({
  for (i in 1:1000) {
    coef_binomial_recursivo(n, k)
  }
})

# Mede tempo de execução da função choose (função embutida do R)
tempo_choose <- system.time({
  for (i in 1:1000) {
    choose(n, k)
  }
})

# Mede tempo de execução da função vetorizada
tempo_vetorizado <- system.time({
  for (i in 1:1000) {
    coef_binomial_vetorizado(n, k)
  }
})

# Exibindo os tempos de execução
print(tempo_recursivo)
##    user  system elapsed 
##    0.02    0.00    0.01
print(tempo_choose)
##    user  system elapsed 
##       0       0       0

Comentários sobre o Desempenho

A função recursiva para coeficientes binomiais pode ser ineficiente para valores grandes de n e k devido à natureza exponencial da recursão. A função choose() do R é altamente otimizada e geralmente é a melhor escolha para cálculos práticos. A abordagem vetorizada também pode ser eficiente, mas pode sofrer com problemas de precisão numérica para valores grandes.

Conclusão

Neste relatório, implementamos funções recursivas para calcular a EWMA e coeficientes binomiais, e comparamos seu desempenho com abordagens iterativas e funções já existentes no R. A recursão pode ser elegante, mas nem sempre é a abordagem mais eficiente em termos de desempenho. Para cálculos práticos, especialmente em grandes conjuntos de dados, é recomendável usar funções otimizadas como choose() ou abordagens iterativas.