Pivotagem de variáveis distintas

Olá.

Estou trabalhando com dados de painel e preciso pivotá-los. Para uma variável, não tenho dificuldades de fazê-lo, mas para mais de uma, preciso de ajuda. Trata-se de uma base de dados de alunos de várias cidades, séries e reprovações. Preciso privotar as várias série por diferentes níveis de ensino e reprovação. Vou fazer um exemplo para ajudar a compreender melhor.

Exemplo

library(tidyverse)

base <- data.frame(
  Escolas = c("escola1", "escola2", "escola3", "escola4"),
  ano1 = c(100, 120, 130, 150),
  rep1 = c(10, 10, 3, 4),
  ano2 = c(120, 120, 130, 170),
  rep2 = c(10, 5, 3, 4),
  ano3 = c(140, 120, 130, 150),
  rep3 = c(10, 5, 3, 0),
  ano4 = c(100, 120, 130, 250),
  rep4 = c(10, 5, 3, 4),
  ano5 = c(100, 120, 130, 240),
  rep5 = c(10, 5, 3, 4),
  ano6 = c(110, 120, 120, 110),
  rep6 = c(12, 5, 3, 4),
  ano7 = c(70, 120, 130, 150),
  rep7 = c(10, 5, 3, 4),
  ano8 = c(80, 120, 130, 150),
  rep8 = c(10, 5, 3, 4),
  ano9 = c(90, 120, 130, 150),
  rep9 = c(10, 5, 3, 4)
  
)

# Eu preciso dividir em três grupos: Basico1, Basico2, Basico37
# O Basico1 é formado por: ano1, ano2, ano3 e ano 4, com suas respectivas reprovações
# Re-_Basico1: rep1, rep2, rep3, rep4

# Os dois outros grupos são:

# Basico2: ano4 e ano 4 e Rep_Basico2: rep4 e rep5
# Basico3: ano7, ano8 e ano9 e Rep_Basico3: rep7, rep8, rep9

# São vários processos de agrupamento e só consigo pivotar uma vez


base_tidy <- base |> tidyr::pivot_longer(
      cols = c(ano1, ano2, ano3, ano4),
      names_to = "Basico1",
      values_to = "Total de alunos")
)

# Faltam agrupar outras duas categrias de "anos" (ano 5 a ano9) e todas as repovações.
# o resultado final agrupa os anos escolares e repovações em três classes.
# Não tenho ideia como fazer  

Hidelbrando,

Tentei entender como você gostaria que os dados ficassem, mas sem um exemplo completo foi meio difícil. A minha principal dúvida é se você quer apenas uma coluna Total de alunos para toda a base tidy ou se você quer uma coluna Total de alunos basico 1, uma coluna Total de alunos basico 2, etc.

Para o primeiro caso, a solução é fácil: basta fazer um pivot_longer() em todas as colunas (exceto Escolas) e depois criar uma coluna grupo com base no nome da turma. O segundo caso é mais difícil e a tabela não seria de fato tidy… Como cada grupo tem um número diferente de turmas, não teria como deixá-los lado a lado sem preencher os vazios com NA.

# Tabela exemplo
base <- data.frame(
  escolas = c("escola1", "escola2", "escola3", "escola4"),
  ano1 = c(100, 120, 130, 150),
  rep1 = c(10, 10, 3, 4),
  ano2 = c(120, 120, 130, 170),
  rep2 = c(10, 5, 3, 4),
  ano3 = c(140, 120, 130, 150),
  rep3 = c(10, 5, 3, 0),
  ano4 = c(100, 120, 130, 250),
  rep4 = c(10, 5, 3, 4),
  ano5 = c(100, 120, 130, 240),
  rep5 = c(10, 5, 3, 4),
  ano6 = c(110, 120, 120, 110),
  rep6 = c(12, 5, 3, 4),
  ano7 = c(70, 120, 130, 150),
  rep7 = c(10, 5, 3, 4),
  ano8 = c(80, 120, 130, 150),
  rep8 = c(10, 5, 3, 4),
  ano9 = c(90, 120, 130, 150),
  rep9 = c(10, 5, 3, 4)
  
)

# Cenário 1
# Base tidy com a correspondência entre turmas e grupos
base |>
  tidyr::pivot_longer(c(-escolas), names_to = "turma", values_to = "total") |>
  dplyr::mutate(
    grupo = dplyr::case_when(
      turma %in% c("ano1", "ano2", "ano3", "ano4") ~ "Basico1",
      turma %in% c("rep1", "rep2", "rep3", "rep4") ~ "Rep_Basico1",
      turma %in% c("ano5", "ano6") ~ "Basico2",
      turma %in% c("rep5", "rep6") ~ "Rep_Basico2",
      turma %in% c("ano7", "ano8", "ano9") ~ "Basico3",
      turma %in% c("rep7", "rep8", "rep9") ~ "Rep_Basico3"
    )
  )
#> # A tibble: 72 × 4
#>    escolas turma total grupo      
#>    <chr>   <chr> <dbl> <chr>      
#>  1 escola1 ano1    100 Basico1    
#>  2 escola1 rep1     10 Rep_Basico1
#>  3 escola1 ano2    120 Basico1    
#>  4 escola1 rep2     10 Rep_Basico1
#>  5 escola1 ano3    140 Basico1    
#>  6 escola1 rep3     10 Rep_Basico1
#>  7 escola1 ano4    100 Basico1    
#>  8 escola1 rep4     10 Rep_Basico1
#>  9 escola1 ano5    100 Basico2    
#> 10 escola1 rep5     10 Rep_Basico2
#> # … with 62 more rows
#> # ℹ Use `print(n = ...)` to see more rows

# Função auxiliar para o cenário 2
renomear <- function(df) {
  novos_nomes <- paste0(names(df), "_", df$grupo[1])[-4]
  df |>
    dplyr::select(-grupo) |>
    purrr::set_names(novos_nomes)
}

# Cenário 2
# Como você daria col_bind() nessas tabelas de tamanhos diferentes?
base |>
  tidyr::pivot_longer(c(-escolas), names_to = "turma", values_to = "total") |>
  dplyr::mutate(
    grupo = dplyr::case_when(
      turma %in% c("ano1", "ano2", "ano3", "ano4") ~ "Basico1",
      turma %in% c("rep1", "rep2", "rep3", "rep4") ~ "Rep_Basico1",
      turma %in% c("ano5", "ano6") ~ "Basico2",
      turma %in% c("rep5", "rep6") ~ "Rep_Basico2",
      turma %in% c("ano7", "ano8", "ano9") ~ "Basico3",
      turma %in% c("rep7", "rep8", "rep9") ~ "Rep_Basico3"
    )
  ) |>
  dplyr::filter(!stringr::str_detect(grupo, "Rep")) |> # Para diminuir a saída
  dplyr::group_split(grupo) |>
  purrr::map(renomear)
#> [[1]]
#> # A tibble: 16 × 3
#>    escolas_Basico1 turma_Basico1 total_Basico1
#>    <chr>           <chr>                 <dbl>
#>  1 escola1         ano1                    100
#>  2 escola1         ano2                    120
#>  3 escola1         ano3                    140
#>  4 escola1         ano4                    100
#>  5 escola2         ano1                    120
#>  6 escola2         ano2                    120
#>  7 escola2         ano3                    120
#>  8 escola2         ano4                    120
#>  9 escola3         ano1                    130
#> 10 escola3         ano2                    130
#> 11 escola3         ano3                    130
#> 12 escola3         ano4                    130
#> 13 escola4         ano1                    150
#> 14 escola4         ano2                    170
#> 15 escola4         ano3                    150
#> 16 escola4         ano4                    250
#> 
#> [[2]]
#> # A tibble: 8 × 3
#>   escolas_Basico2 turma_Basico2 total_Basico2
#>   <chr>           <chr>                 <dbl>
#> 1 escola1         ano5                    100
#> 2 escola1         ano6                    110
#> 3 escola2         ano5                    120
#> 4 escola2         ano6                    120
#> 5 escola3         ano5                    130
#> 6 escola3         ano6                    120
#> 7 escola4         ano5                    240
#> 8 escola4         ano6                    110
#> 
#> [[3]]
#> # A tibble: 12 × 3
#>    escolas_Basico3 turma_Basico3 total_Basico3
#>    <chr>           <chr>                 <dbl>
#>  1 escola1         ano7                     70
#>  2 escola1         ano8                     80
#>  3 escola1         ano9                     90
#>  4 escola2         ano7                    120
#>  5 escola2         ano8                    120
#>  6 escola2         ano9                    120
#>  7 escola3         ano7                    130
#>  8 escola3         ano8                    130
#>  9 escola3         ano9                    130
#> 10 escola4         ano7                    150
#> 11 escola4         ano8                    150
#> 12 escola4         ano9                    150

Created on 2022-08-02 by the reprex package (v2.0.1)

1 curtida

Olá Caio, obrigado pela resposta. Vou olhar com atenção e ver se atende ao que preciso. Depois te dou um feedback.