Arquivos CSV com padrão de encoding de texto diferente (Windows)

Infelizmente me tornei a criadora da etiqueta “Windows” neste fórum rs.

Gente,

Tem uns arquivos que o governo de SP divulga todo dia, mas cada dia meu Windows abre a planilha com um encoding diferente. É um arquivo por dia, então estou automatizando um código pra juntar todos eles e criar meu próprio histórico.

Estou tentando fazer uma limpeza inicial no Visual Studio Code pra ver se resolve, porque pelo Bloco de Notas não resolve também.

Vou dar os exemplos mais recentes:
https://www.saopaulo.sp.gov.br/wp-content/uploads/2021/01/20210118_leitos_ocupados_por_unidade_hospitalar.csv

https://www.saopaulo.sp.gov.br/wp-content/uploads/2021/01/20210117_leitos_ocupados_por_unidade_hospitalar.csv

https://www.saopaulo.sp.gov.br/wp-content/uploads/2021/01/20210116_leitos_ocupados_por_unidade_hospitalar.csv

https://www.saopaulo.sp.gov.br/wp-content/uploads/2021/01/20210115_leitos_ocupados_por_unidade_hospitalar.csv

Se eu abro cada arquivo no Excel, os acentos estão todos OK.

Mas eu só rodo um código pra puxar os arquivos e abrir no RStudio, o arquivo de 18/01 abre com os acentos corretos. Mas os demais abrem com encoding todo bagunçado. Testei em dois computadores diferentes (todos com Windows).

Queria saber se o problema sou eu e o meu Windows ou do cara que exporta esse CSV cada dia de um jeito (e aí não tenho como saber em que dia vai dar chabu, ou seja, inviabiliza a automatização).

E se existe algum caminho pra eu automatizar a abertura dessa planilha e a padronização do encoding de uma vez por todas. Talvez passar todas as planilhas por um mesmo tratamento automaticamente, antes do meu código pra criar uma coluna de data, juntar as planilhas e fazer um pivot_wider.

PRINT DO DATAFRAME DE 18/01 ARRUMADINHO NO RSTUDIO:

PRINT DO DATAFRAME DE 15/01 ZOADAÇO NO RSTUDIO:

1 Curtida

Alguns arquivos estão em UTF-8 e outros em ISO-8859 (ou ISO-8859-15 ou LATIN-1):

$ file *leitos*csv
20210115_leitos_ocupados_por_unidade_hospitalar.csv:     UTF-8 Unicode (with BOM) text, with CRLF line terminators
20210116_leitos_ocupados_por_unidade_hospitalar.csv:     UTF-8 Unicode (with BOM) text, with CRLF line terminators
20210117_leitos_ocupados_por_unidade_hospitalar.csv:     UTF-8 Unicode (with BOM) text, with CRLF line terminators
20210118_leitos_ocupados_por_unidade_hospitalar.csv:     ISO-8859 text, with CRLF line terminators

Não sei como faz em R, mas você precisará checar se o arquivo está em uma codificação ou outra, para depois fazer a decodificação final e então usar os dados. Talvez exista alguma biblioteca que, baseada no conteúdo do arquivo, tente prever a codificação (não é 100% de certeza). Acima eu usei o comando file, que faz exatamente isso (em Python tem uma biblitoeca chamada file-magic e outra chamada chardet que fazem exatamente isso).

Minha sugestão, dado que sei quase nada de R: caso não exista uma biblioteca que faça isso, tente decodificar em ISO-8859-15 e, se der erro ou se o resultado for algo que contenha “Ô e/ou “§”, daí tente UTF-8.

O pacote readr tem a função guess_encoding que lista o encoding mais provável, só que nesse caso ele retorna que UTF-8 é o encoding mais provável mesmo quando o encoding é certo é latin1. Porém, quando é latin1 ele não dá 100% de certeza (a coluna confidence é menor que 1). Sabendo disso dá para fazer ele acertar (qdo ele não tem certeza, é pq é latin1). Não tem como ter certeza que essa função vai funcionar 100% dos casos, mas para os exemplos de tabelas que você forneceu rolou por aqui (estou em um linux, mas acho que isso nào deve fazer diferença). Se não funcionar em algum caso se pode tentar diminuir o valor de limiar_para_ser_latin1.

library(readr)
read.csv_guess_encoding <- function(file, limiar_para_ser_latin1 = 1, ...){
  # Lista os encoding mais prováveis
  enc_list <- guess_encoding(file, n_max = 100000)  
  # Seleciona o mais provável
  enc1 <- enc$encoding[1]
  # Quando ele tem 100% de certeza que é UTF-8 é pq é. 
  # Se ele tem dúvida é pq é latin1
  if(max(enc_list$confidence) < limiar_para_ser_latin1){
    enc1 <- "latin1"
  }
  read.csv(file, encoding = enc1, ...)
}