Importar, verificar e gravar dados quando os ficheiros não cooperam.
Autores
Afiliações
João O. Santos
ISPA
Cristina Mendonça
ISPA; WJCR
Vitória Melita
FP-UL
Mariona Pascual Peñas
UIB
João Raposo
ISPA
Marta Barros
FP-UL
0 Importação e Exportação de Dados
Importar dados não é só escolher uma função que combine com a extensão do ficheiro. O R conseguir abrir um ficheiro não significa que o leu como queríamos. Convém confirmar que é o ficheiro certo, no caminho certo, com o separador, a codificação e os tipos que esperávamos.
Nesta página vamos partir de alguns problemas comuns e ver que verificações os detectam. Se ainda não trabalhou com tabelas no R, a introdução aos data.frames explica o tipo de objecto que estas funções vão criar.
NotaDetalhes geek
Um ficheiro no disco e um objecto na memória são coisas diferentes:
file on disk ≠ R object in memory
O working directory é o ponto de partida para caminhos relativos, como ../data/demo_ds.csv; .. significa a pasta acima. Um caminho absoluto indica toda a localização e pode funcionar apenas no computador de quem o escreveu. Num projecto, uma estrutura previsível e caminhos relativos costumam ser mais portáveis.
O objecto vive na memória RAM, dentro da sessão R. Alterá-lo não altera o ficheiro original. Só uma operação de escrita, como write.csv(), cria ou substitui um ficheiro. Esta distinção parece básica, mas resolve muita confusão quando começamos a importar e exportar dados.
O Fluxo Mínimo
Na prática, o fluxo é simples: ler, inspeccionar, só depois escrever. Para não confundirmos a origem com o resultado, damos nomes e caminhos diferentes aos dois. Faça estes passos num script. Abrir a folha de cálculo à mão pode ajudar a explorar, mas não deixa um rasto fácil de repetir.
# Only after checking and transforming the data:ficheiro_copia<-tempfile("demo_ds_copia_", fileext =".csv")write.csv(dados, ficheiro_copia, row.names =FALSE)
Aqui tempfile() cria um caminho temporário para que o exemplo possa ser renderizado sem alterar a pasta data/. Num projecto real, substitua-o por um caminho de saída documentado, diferente do original, e confirme que tem permissão para escrever nessa pasta.
Erro: Ficheiro Não Encontrado
Um caminho relativo parte do working directory da sessão, não da pasta que está aberta no gestor de ficheiros. Não há uma pasta secreta do R: é apenas o ponto a partir do qual ele começa a interpretar caminhos relativos. Antes de mudar nomes ao acaso, veja onde está e teste se o ficheiro existe.
Se file.exists() devolver FALSE, confirme o directório, a grafia, maiúsculas/minúsculas e a localização do ficheiro. Para uma escolha pontual, file.choose() devolve o caminho seleccionado na interface:
Num projecto partilhado, é normalmente preferível manter uma estrutura previsível e usar caminhos relativos. setwd() pode ser útil numa sessão, mas um setwd() com o caminho pessoal de quem escreveu o script torna-o frágil noutra máquina.
Erro: Formato ou Separador
CSV significa valores separados por um delimitador, mas esse delimitador nem sempre é uma vírgula. Se todas as colunas aparecerem coladas umas às outras, confirme o separador e a codificação antes de concluir que os dados estão estragados.
# Comma: the usual option for read.csv().dados_csv<-read.csv("../data/demo_ds.csv")# A tab-separated file uses read.delim().dados_tsv<-read.delim("../data/lobsters-2016.tsv")head(dados_csv)
Se os acentos ou outros caracteres aparecerem corrompidos, confirme também a codificação em que o ficheiro foi gravado. Funções como read.csv() aceitam o argumento fileEncoding; indique-o apenas depois de identificar a codificação, e volte a inspeccionar nomes e valores em vez de presumir que a leitura ficou correcta.
A extensão .xlsx requer um pacote. Instale-o uma vez, fora do script. Depois pode carregar readxl no início da sessão ou chamar a função com o nome do pacote:
# Run installation once, outside the analysis script.install.packages("readxl")
# Read a small, real sample so the example remains quick to render.dados_excel<-readxl::read_excel("../data/global-shark-attack.xlsx", n_max =10, .name_repair ="minimal")dim(dados_excel)
Ficheiros .sav e outros formatos de programas estatísticos também precisam de uma função ou pacote adequado. Consulte a documentação e, sobretudo, inspeccione o objecto depois da leitura. Uma função terminar sem erro só nos diz que terminou sem erro.
Erro: Linhas Extra
Algumas plataformas de recolha acrescentam linhas de metadados entre os nomes das colunas e as respostas dos participantes. Quando isso acontece, números e datas podem entrar no R como character porque as primeiras linhas contêm texto.
Se a inspecção mostrar que há linhas extra, remova-as numa cópia e volte a examinar o resultado. O número de linhas a retirar depende do ficheiro que tem à frente; não transforme o -c(1, 2) deste exemplo numa regra geral.
qualtrics<-raw[-c(1, 2), , drop =FALSE]head(qualtrics)
Se uma variável numérica continuar como texto, veja os valores antes de a converter. Uma conversão cega pode transformar valores mal formados em NA e fazer desaparecer precisamente a pista de que havia um problema.
Erro: Importação Não Verificada
Mesmo quando o ficheiro abre, convém confirmar pelo menos:
o caminho e o número de linhas e colunas;
os nomes das colunas e as suas classes;
algumas linhas do início e do fim;
valores em falta, intervalos e identificadores duplicados, quando forem relevantes para a pergunta.
Estas verificações não provam que os dados são válidos. Servem para tornar algumas expectativas explícitas e para nos dar um ponto concreto de partida quando alguma coisa muda. A limpeza de dados começa precisamente quando uma destas perguntas revela algo que exige uma decisão.
Exportar sem Perder a Origem
Depois de documentar as decisões, escrevemos uma nova versão. row.names = FALSE evita acrescentar ao CSV uma coluna com os nomes automáticos das linhas.
tempfile() mantém este exemplo seguro durante o render. Um percurso de ida e volta por CSV não preserva necessariamente todas as classes e atributos do R; datas, por exemplo, podem precisar de nova conversão depois da leitura. É por isso que vale a pena verificar mais do que a simples existência do novo ficheiro.
No seu projecto, guarde o original, registe as transformações e escreva a versão nova noutro caminho. Assim pode repetir a análise ou rever uma decisão sem depender da memória ou de cliques que já ninguém sabe reconstruir.
Exercícios
Use file.exists() e getwd() para explicar por que razão um caminho relativo pode funcionar num computador e falhar noutro.
Um caminho relativo é interpretado a partir do working directory. Se duas sessões começarem em pastas diferentes, a mesma string pode apontar para ficheiros diferentes ou para nenhum ficheiro.
Importe demo_ds.csv, inspeccione-o e escreva três verificações que confirmem que a importação corresponde à sua expectativa.
Estas verificações confirmam a origem, a existência de registos e a presença de colunas esperadas. A validade científica dos valores exige outras verificações.
Inspeccione raw_qualtrics.csv. Identifique, com código e não apenas à vista, sinais de cabeçalhos extra ou classes inesperadas. Grave uma cópia corrigida sem substituir o original.
raw_corrigido<-raw_exercicio[!linhas_extra, , drop =FALSE]ficheiro_corrigido<-tempfile("raw_qualtrics_corrigido_", fileext =".csv")write.csv(raw_corrigido, ficheiro_corrigido, row.names =FALSE)
Aqui o critério identifica as duas linhas de metadados pelos seus valores, em vez de depender apenas da posição. A cópia temporária não substitui o original.
Importe um ficheiro Excel com readxl e explique qual é a dependência do script e que verificações faria antes de o analisar.
tibble [10 × 21] (S3: tbl_df/tbl/data.frame)
$ Date : chr [1:10] "2023-07-29" "2023-04-22" "2023-03-02" "2023-02-18" ...
$ Year : chr [1:10] "2023" "2023" "2023" "2023" ...
$ Type : chr [1:10] "Unprovoked" "Unprovoked" "Unprovoked" "Questionable" ...
$ Country : chr [1:10] "USA" "AUSTRALIA" "SEYCHELLES" "ARGENTINA" ...
$ Area : chr [1:10] "Florida" "Western Australia" "Praslin Island" "Patagonia" ...
$ Location : chr [1:10] "Tampa Bay" "Lucy's Beach" NA "Chubut Province" ...
$ Activity : chr [1:10] "Swimming" "Surfing" "Snorkeling" NA ...
$ Name : chr [1:10] "Natalie Branda" "Max Marsden" "Arthur …" "Diego Barría" ...
$ Sex : chr [1:10] "F" "M" "M" "M" ...
$ Age : chr [1:10] "26" "30" "6" "32" ...
$ Injury : chr [1:10] "Superficial injuries to abomen and thighs" "Bite to right arm" "Left foot bitten" "Death by misadventure" ...
$ Fatal (Y/N) : chr [1:10] "N" "N" "UNKNOWN" "UNKNOWN" ...
$ Time : chr [1:10] "20h00" "07h15" "Afternoon" NA ...
$ Species : chr [1:10] NA "Bronze whaler shark, 1.5 m" "Lemon shark" NA ...
$ Investigator or Source: chr [1:10] "Fox12, 8/1/2023" "The West Australian, 4/22/2023" "Midlibre, 3/18/2023" "El Pais, 2/27/2023" ...
$ pdf : chr [1:10] NA NA NA NA ...
$ href formula : chr [1:10] NA NA NA NA ...
$ href : chr [1:10] NA NA NA NA ...
$ Case Number : chr [1:10] NA NA NA NA ...
$ Case Number : chr [1:10] NA NA NA NA ...
$ original order : chr [1:10] NA NA NA NA ...
A dependência é o pacote readxl; a instalação é preparação do ambiente, não parte do script de análise. Antes de analisar, confirmaria o ficheiro, as colunas, as classes, algumas linhas e os valores em falta.
Exporte uma pequena tabela para um caminho criado por tempfile(), volte a importá-la e compare nomes, dimensões e classes. Que propriedades não pode concluir que um CSV preservará sempre?
Solução 5
tabela<-data.frame(id =1:2, valor =c(2.5, 4.0))ficheiro<-tempfile("tabela_", fileext =".csv")write.csv(tabela, ficheiro, row.names =FALSE)reimportada<-read.csv(ficheiro)names(tabela)
Um CSV conserva texto e uma representação tabular simples, mas não garante todas as classes e atributos do R. Por exemplo, datas, factores e atributos específicos podem precisar de conversão ou reconstrução.