Como crio uma coluna defasada de 1 mês com critério por outra coluna?

Boa noite pessoal, tudo bem com vocês?
Hoje meu irmão mais novo me pediu uma ajuda e eu tentei ajudar de algumas formas mas não consegui. Venho aqui pedir o suporte de vocês por favor.

Nós precisamos criar uma coluna que traga os valores defasados de 1 mês. A estrutura da tabela hoje é mais ou menos essa aqui.

PS: Em concatenar, estão os valores das chaves que devem ser consideradas para trazer o valor de 1 mês atrás.

Como os anos se repetem, eu pensei em primeiro criar uma coluna concatenando os valores de ano e mês

mod$anomes<- paste0(mod$ANO,mod$MES) |> as.numeric()

E além disso, apenas como suporte se fosse necessário, também criei uma coluna de data, mas na granularidade mensal, ou seja, eu tenho apenas o primeiro dia do mês para qualquer valor na coluna concatenar.

mod$data<- paste0(mod$ANO,"-",mod$MES,"-01") |> as.Date()

Depois disso, eu pensei em criar um agrupamento por data para gerar a coluna que chamei de v1

mod |> 
  group_by(data) |> 
  mutate(v1 = dplyr::lag(v, n = 1)) 

para trazer os valores defasados com a função lag.

Mas o resultado que eu consegui, gerou a defasagem para linha de cima e não para o mês anterior e até aqui, eu não consegui realizar essa operação considerando a chave em concatenar e o lag de 1 mês.

Então na futura coluna v1, eu preciso colocar o valor de v no mês passado para aquela chave.

Esse é meu primeiro post aqui, peço desculpas caso não tenha seguido o padrão de postagens e prometo continuar aprendendo.

Alguém consegue por favor me ajudar com essa questão? Ao meu ver é um lag com critérios, mas em outra coluna (coluna chave), então a lógica seria. Quando a chave for essa, qual foi o valor de v no mês passado? E esse valor é inserido em v1 para das as observações da base.

Veja se o código abaixo atende aos seus requisitos:

library(tidyverse)
library(lubridate)

# Tabela de exemplo
mod <- tribble(
  ~concatenar, ~ANO, ~MES, ~v,
  "chave1", 2020, 1, "valor1",
  "chave2", 2020, 1, "valor2",
  "chave1", 2020, 2, "valor3",
  "chave2", 2020, 2, "valor4",
  "chave1", 2020, 3, "valor5",
  "chave2", 2020, 3, "valor6"
)

mod <- mod |>
  mutate(data = make_date(ANO, MES))

mod_lag <- mod |>
  mutate(data_lag = data + months(1)) |>
  select(concatenar_lag = concatenar, data_lag, v_lag = v)

mod |>
  left_join(mod_lag, c("concatenar" = "concatenar_lag", "data" = "data_lag"))
#> # A tibble: 6 × 6
#>   concatenar   ANO   MES v      data       v_lag 
#>   <chr>      <dbl> <dbl> <chr>  <date>     <chr> 
#> 1 chave1      2020     1 valor1 2020-01-01 <NA>  
#> 2 chave2      2020     1 valor2 2020-01-01 <NA>  
#> 3 chave1      2020     2 valor3 2020-02-01 valor1
#> 4 chave2      2020     2 valor4 2020-02-01 valor2
#> 5 chave1      2020     3 valor5 2020-03-01 valor3
#> 6 chave2      2020     3 valor6 2020-03-01 valor4

Created on 2022-11-21 with reprex v2.0.2

1 curtida

Oi Caio, boa tarde! Nossa, sim! É um resultado como esse que eu preciso.

Eu fiz uma execução criando outro objeto.

mod <- mod |>
  mutate(data = make_date(ANO, MES))


mod_lag <- mod |>
  mutate(data_lag = data + months(1)) |>
  select(concatenar_lag = concatenar, data_lag, v_lag = v)

mod2 <- mod |>
  left_join(mod_lag, c("concatenar" = "concatenar_lag", "data" = "data_lag"))

Entretanto no meu caso, a coluna toda voltou como NA.
Eu esqueci de comentar, que é possível que para algumas chaves eu não tenha valores no mês anterior, mas ainda não identifiquei se teria influencia para retornar toda a coluna como NA.

Segue um print do resultado.

image

Uma das coisas que eu notei é que preciso subtrair 1 mês, creio que seja necessário mudar nesse trecho.

mod_lag <- mod |>
  mutate(data_lag = data - months(1)) |>
  select(concatenar_lag = concatenar, data_lag, v_lag = v)

Vou continuar investigando essa questão do rertono full NA e agradeço muito pelo esclarecimento até aqui. Qualquer nova sugestão será muito bem vinda.

Estranho a coluna estar voltando inteira com NAs. Isso é esperado para o primeiro mês da base, pois não há um mês anterior, mas não para a base toda. Será que a coluna concatenar está correspondendo de forma correta? Sem ver o resto da base fica difícil de imaginar de onde vem o erro :thinking:

Sobre a questão de subtrair ou somar 1 mês, eu acho que o certo seria + months(1) mesmo. Se eu entendi direito, você precisa que a v_lag seja o valor de v 1 mês antes; sendo assim, a gente precisa que data_lag seja a data do mês seguinte.

# SOMANDO 1 mês
mod_lag <- mod |>
  mutate(data_lag = data + months(1)) |>
  select(concatenar_lag = concatenar, data_lag, v_lag = v)

mod |>
  left_join(mod_lag, c("concatenar" = "concatenar_lag", "data" = "data_lag"))
#> # A tibble: 6 × 6
#>   concatenar   ANO   MES v      data       v_lag 
#>   <chr>      <dbl> <dbl> <chr>  <date>     <chr> 
#> 1 chave1      2020     1 valor1 2020-01-01 <NA>  
#> 2 chave2      2020     1 valor2 2020-01-01 <NA>  
#> 3 chave1      2020     2 valor3 2020-02-01 valor1
#> 4 chave2      2020     2 valor4 2020-02-01 valor2
#> 5 chave1      2020     3 valor5 2020-03-01 valor3
#> 6 chave2      2020     3 valor6 2020-03-01 valor4

# SUBTRAINDO 1 mês
mod_lag <- mod |>
  mutate(data_lag = data - months(1)) |>
  select(concatenar_lag = concatenar, data_lag, v_lag = v)

mod |>
  left_join(mod_lag, c("concatenar" = "concatenar_lag", "data" = "data_lag"))
#> # A tibble: 6 × 6
#>   concatenar   ANO   MES v      data       v_lag 
#>   <chr>      <dbl> <dbl> <chr>  <date>     <chr> 
#> 1 chave1      2020     1 valor1 2020-01-01 valor3
#> 2 chave2      2020     1 valor2 2020-01-01 valor4
#> 3 chave1      2020     2 valor3 2020-02-01 valor5
#> 4 chave2      2020     2 valor4 2020-02-01 valor6
#> 5 chave1      2020     3 valor5 2020-03-01 <NA>  
#> 6 chave2      2020     3 valor6 2020-03-01 <NA>

Veja os dois exemplos acima. No primeiro, o v_lag corresponde ao valor de v para a mesma chave 1 mês antes. No segundo, o v_lag corresponde ao valor de v para a mesma chave 1 mês depois.

1 curtida

Entendi a questão do - months(1). Muito obrigado Caio! Creio que seja esse caminho que precisamos seguir por aqui. Agora estamos tentando identificar o motivo do retorno de NAs. A chave é um valor de texto, relativamente longo, resultado da concatenação de alguns campos do dataset. Estou pensando em quais condições resultaria em nenhum match? Sendo que para maioria das chaves, existem valores nos meses anteriores. Infelizmente eu não tenho autorização para enviar os dados aqui de forma pública, mas continuaremos pensando em uma solução.

Olá! De fato tinha um problema na chave. A versão que existia no excel, por alguma regra necessária para o Excel, estava considerando no concat o mês e o ano, logo, o left_join retornava totalmente NA, pois ele não encontraria na lag uma chave com o mesmo ano e mês. Resolvendo isso, resolveu todo o problema. Muito obrigado, Caio. Ajudou demais.