Leitura de arquivos com informações em blocos

Oi Pessoal,
Estou trabalhando com um arquivo (disponível aqui) que contém blocos anuais de informações diárias de chuva, como mostrado (parcialmente) na imagem abaixo.

Venho tentando fazer a leitura e organização deste arquivo de modo que eu possa ter ao final um data.frame ou tibble com colunas: “name_file”, “lon”, “lat”, “data” e “prec”. Talvez não seja a melhor forma mas pensei em fazer a leitura de cada bloco separadamente uilizando uma estrutura de repetição. Abaixo tem o uso da função read.table() para leitura do primeiro bloco de informação:

read.table("DiarioÁgua Branca (02).wri", header = T, skip = 6, 
    fill = T, nrows = 31)
#>    DIA  JAN  FEV MAR  ABR  MAI JUN JUL AGO SET OUT NOV DEZ
#> 1    1  0.0 10.1 0.0  0.0 57.1 0.0   0  NA  NA  NA  NA  NA
#> 2    2  2.4  4.6 0.0  0.0  7.0 0.0   0  NA  NA  NA  NA  NA
#> 3    3 24.7  7.0 0.0  0.0  7.2 0.0   0  NA  NA  NA  NA  NA
#> 4    4  3.5  0.0 0.5  0.0  0.6 0.0   0  NA  NA  NA  NA  NA
#> 5    5  0.0  0.0 2.9  0.0  3.9 0.0   0  NA  NA  NA  NA  NA
#> 6    6  1.3  0.0 0.0  0.0  1.6 0.0   0  NA  NA  NA  NA  NA
#> 7    7  2.1  2.5 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 8    8 12.1  2.5 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 9    9  4.3  8.8 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 10  10  2.7 12.4 3.8 18.6  0.0 0.0   0  NA  NA  NA  NA  NA
#> 11  11  4.3 38.5 0.0 21.9  0.0 0.0   0  NA  NA  NA  NA  NA
#> 12  12  4.8 10.6 0.7 21.2  0.0 0.0   0  NA  NA  NA  NA  NA
#> 13  13  1.3  8.8 0.3  8.3  0.0 0.0   0  NA  NA  NA  NA  NA
#> 14  14 21.5 11.7 2.6  1.5  0.0 0.0   0  NA  NA  NA  NA  NA
#> 15  15  0.0  5.6 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 16  16  0.0  0.0 0.0  0.0  2.2 0.0   0  NA  NA  NA  NA  NA
#> 17  17  0.5  0.0 0.0  6.5  0.0 0.0   0  NA  NA  NA  NA  NA
#> 18  18  2.9  0.0 0.0  4.1  0.0 0.0   0  NA  NA  NA  NA  NA
#> 19  19  0.0  0.4 1.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 20  20  0.0  1.8 4.4  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 21  21  2.5  0.0 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 22  22  2.8  0.0 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 23  23  0.0  0.0 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 24  24  0.0  0.0 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 25  25  0.0  2.3 1.0  0.0  0.0 1.6   0  NA  NA  NA  NA  NA
#> 26  26  0.0 41.0 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 27  27  0.0  0.0 0.4  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 28  28  0.0  0.0 0.0  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 29  29  0.0  0.0 0.8  0.0  0.0 0.0   0  NA  NA  NA  NA  NA
#> 30  30  0.9  0.0 0.0  0.0  0.0 5.9   0  NA  NA  NA  NA  NA
#> 31  31  0.0  0.4 0.0  0.0   NA  NA  NA  NA  NA  NA  NA  NA

Created on 2022-03-21 by the reprex package (v2.0.1)

Sobre esta abordagem, observe que encontro o primeiro problema: os meses de agosto (AGO) a dezembro (DEZ) recebem NA, porém, são os meses de janeiro (JAN) a maio (MAI) que devem receber NA, como visto na imagem acima. Tentei fazer a leitura também com readLines() mas não obtive grande avanço. Qualquer ajuda na leitura e organização desses dados é bem-vinda. Muito obrigado!

Oi Samuel, tudo bem? Obrigada por deixar a base disponível com a dúvida!

Quando eu preciso importar uma base que não está organizada, e que depende da posição, eu uso a função readr::read_fwf() :

Aí a importação usa uma largura oferecida por nós para quebrar as colunas. Esse tipo de importação é um pouco chato pois depende da estrutura ser sempre igual (E pelo que vi no seu arquivo, é sempre igual), e precisamos criar um vetor manualmente com as posicoes onde cada coluna se inicia.

Depois disso foi muito tidyverse pra organizar a base. Talvez tenha formas mais fáceis mas foi essa que eu pensei. Ainda falta você tratar as colunas depois (com o mutate) e deixar nas classes corretas.

# caminho do arquivo
file <- "~/Downloads/DiarioÁgua Branca (02).wri"

# descobrir encoding
encoding_adivinhado <- readr::guess_encoding(file) |>
  dplyr::slice(1) |>
  dplyr::pull(encoding)

# posicoes de inicio e final da coluna
positions_start <- c(1, # dia
                     10, # jan
                     20, # fev
                     30, # mar
                     38, # abr
                     48, # maio
                     56, # junho
                     66, # julho
                     74, # agosto
                     84, # setembro
                     92, # outubro
                     102, # novembro
                     111) # dezembro

positions_end <- c(positions_start[-1] - 1, NA)

# ler a base  com essas posicoes separando as colunas
pos <- readr::fwf_positions(
  start = positions_start,
  end =   positions_end,
  col_names = c(
    "dia",
    "mes_janeiro",
    "mes_fevereiro",
    "mes_marco",
    "mes_abril",
    "mes_maio",
    "mes_junho",
    "mes_julho",
    "mes_agosto",
    "mes_setembro",
    "mes_outubro",
    "mes_novembro",
    "mes_dezembro"

  )
)

tab_raw <-
  readr::read_fwf(
    file,
    col_positions = pos,
    show_col_types = FALSE,
    locale = readr::locale(encoding = encoding_adivinhado)
  )

# manipulando a base pra ficar organizado

tabela_precipitacao <- tab_raw |>
  dplyr::mutate(
    dia =   tidyr::replace_na(dia, " "),
    name_file = basename(file),
    quebra = stringr::str_detect(dia,
                                 "Secretari"),
    id_tabela = cumsum(quebra),
    .before = tidyselect::everything()
  ) |>
  dplyr::select(-quebra) |>
  dplyr::group_split(id_tabela) |>
  purrr::map(
    ~ .x |>
      tidyr::unite(
        remove = FALSE,
        col = "tudo",
        na.rm = TRUE,
        sep = ""
      ) |>
      dplyr::mutate(
        ano = stringr::str_extract(tudo[5], "(?<=ANO DE)(.*?)$"),
        lat = stringr::str_extract(tudo[4], "(?<=Lat:)(.*?)(?=long:)"),
        long = stringr::str_extract(tudo[4], "(?<=long:)(.*?)$"),
        inicio_traco = stringr::str_starts(dia, "______"),
        cum_sum_traco = cumsum(inicio_traco)
      ) |>
      dplyr::filter(cum_sum_traco == 1) |>
      dplyr::select(-inicio_traco,-cum_sum_traco,-tudo,-id_tabela) |>
      dplyr::slice(-1,-2)

  ) |>
  dplyr::bind_rows() |>
  tidyr::pivot_longer(
    cols = tidyselect::starts_with("mes_"),
    names_prefix = "mes_",
    names_to = "mes",
    values_to = "precipitacao"
  ) |>
  dplyr::relocate(mes, .after = dia)


o resultado:


tabela_precipitacao

# A tibble: 5,208 × 7
# name_file                  dia   mes       ano   lat        long        precipitacao
# <chr>                      <chr> <chr>     <chr> <chr>      <chr>       <chr>
#   1 DiarioÁgua Branca (02).wri 1     janeiro   1973  "-9.2500 " " -37.9167" NA
# 2 DiarioÁgua Branca (02).wri 1     fevereiro 1973  "-9.2500 " " -37.9167" NA
# 3 DiarioÁgua Branca (02).wri 1     marco     1973  "-9.2500 " " -37.9167" NA
# 4 DiarioÁgua Branca (02).wri 1     abril     1973  "-9.2500 " " -37.9167" NA
# 5 DiarioÁgua Branca (02).wri 1     maio      1973  "-9.2500 " " -37.9167" NA
# 6 DiarioÁgua Branca (02).wri 1     junho     1973  "-9.2500 " " -37.9167" 0.0
# 7 DiarioÁgua Branca (02).wri 1     julho     1973  "-9.2500 " " -37.9167" 10.1
# 8 DiarioÁgua Branca (02).wri 1     agosto    1973  "-9.2500 " " -37.9167" 0.0
# 9 DiarioÁgua Branca (02).wri 1     setembro  1973  "-9.2500 " " -37.9167" 0.0
# 10 DiarioÁgua Branca (02).wri 1     outubro   1973  "-9.2500 " " -37.9167" 57.1
# # … with 5,198 more rows

Espero que seja útil! Abraços!

2 curtidas

Oi Beatriz.
Muito obrigado pelo retorno e pela rapidez em responder!!
Utilizo o pacote readr mas não conhecia a função readr::read_fwf(). Ficou exatamente como eu gostaria, vai ser muito útil! Os ajustes finais eu posso fazer.
Abraços,
Valeu :grinning: :grinning:.

Que bom que deu certo, Samuel!! :smiley: fico feliz!
Abraços