Substituindo um for loop

Olá! Estou tentando substituir um for em um código e tenho certeza que é possível, mas não consegui pensar em alguma alternativa. O objetivo é calcular um índice na linha i+1, para fazer isso eu pego o valor da linha i+1, divido por 100 e somo 1, multiplicado pelo índice na linha i. Dá para perceber que o índice é calculado com base no indice anterior, como faço isso de forma tidy?

Agradeço desde já :slight_smile:

saldo_pj <- BETS::BETSget(20540)
#> Registered S3 method overwritten by 'quantmod':
#>   method            from
#>   as.zoo.data.frame zoo
#> Warning: 
#> BETS-package: There is no corresponding entry in the metadata table.
#> 
#>  Don't worry, this is not a critical problem. We are working on a solution.
ipca <-  sidrar::get_sidra(1737,
                           variable = 63,
                           period = c('200703-202110'),
                           geo = 'Brazil', 
                           header = TRUE)
#> Considering all categories once 'classific' was set to 'all' (default)


ipca_mes <- ipca |>
  tibble::as_tibble() |>
  janitor::clean_names() |>
  dplyr::select(mes, valor) |>
  dplyr::mutate(indice = 1)

for (i in 1:nrow(ipca_mes)) {
  ipca_mes[i+1, "indice"] = (ipca_mes[i+1, "valor"]/100+1 )*ipca_mes[i, "indice"]
}

ipca_mes |>
  dplyr::slice(- dplyr::n()) |>
  dplyr::mutate(
    deflator  = dplyr::last(indice) / indice)
#> # A tibble: 176 × 4
#>    mes           valor indice deflator
#>    <chr>         <dbl>  <dbl>    <dbl>
#>  1 março 2007     0.37   1        2.27
#>  2 abril 2007     0.25   1.00     2.27
#>  3 maio 2007      0.28   1.01     2.26
#>  4 junho 2007     0.28   1.01     2.25
#>  5 julho 2007     0.24   1.01     2.25
#>  6 agosto 2007    0.47   1.02     2.24
#>  7 setembro 2007  0.18   1.02     2.23
#>  8 outubro 2007   0.3    1.02     2.23
#>  9 novembro 2007  0.38   1.02     2.22
#> 10 dezembro 2007  0.74   1.03     2.20
#> # … with 166 more rows
1 curtida

Douglacardoso, nesse caso você precisa de uma função chamada accumulate() do pacote purrr. Ela usa o resultado da última aplicação de uma função como argumento da próxima aplicação. Veja se o código está claro e retorna o resultado desejado:

saldo_pj <- BETS::BETSget(20540)
#> Registered S3 method overwritten by 'quantmod':
#>   method            from
#>   as.zoo.data.frame zoo
#> Warning: 
#> BETS-package: There is no corresponding entry in the metadata table.
#> 
#>  Don't worry, this is not a critical problem. We are working on a solution.

ipca <-  sidrar::get_sidra(1737,
  variable = 63,
  period = c("200703-202110"),
  geo = "Brazil",
  header = TRUE
)
#> Considering all categories once 'classific' was set to 'all' (default)

ipca |>
  tibble::as_tibble() |>
  janitor::clean_names() |>
  dplyr::select(mes, valor) |>
  dplyr::mutate(
    indice = valor |>
      dplyr::lead() |>
      head(-1) |>
      purrr::accumulate(~(.y / 100 + 1) * .x, .init = 1)
  )
#> # A tibble: 176 × 3
#>    mes           valor indice
#>    <chr>         <dbl>  <dbl>
#>  1 março 2007     0.37   1   
#>  2 abril 2007     0.25   1.00
#>  3 maio 2007      0.28   1.01
#>  4 junho 2007     0.28   1.01
#>  5 julho 2007     0.24   1.01
#>  6 agosto 2007    0.47   1.02
#>  7 setembro 2007  0.18   1.02
#>  8 outubro 2007   0.3    1.02
#>  9 novembro 2007  0.38   1.02
#> 10 dezembro 2007  0.74   1.03
#> # … with 166 more rows

Created on 2021-12-13 by the reprex package (v2.0.1)

1 curtida

Muito obrigado Caio! Era mais uma dúvida de curiosidade/aprendizado do que de necessidade. Ainda acostumando a usar as funções do purrr.