Importando e exportando dados no R

Esta página foi adaptada da página Importando e Exportando Dados no R, que é parte da disciplina BOT-89 Introdução ao R e Preparação de Dados, ligada ao Programa de Pós-graduação em Ciências Biológicas (Botânica) (PPGBOT) do Instituto Nacional de Pesquisas da Amazônia (INPA), Amazonas, Brasil, e ministrada anualmente pelo Dr. Alberto Vicentini (INPA). Neste ano de 2020, o professor Alberto Vicentini, que foi meu coorientador de meu doutorado cursado neste mesmo Programa de pós-graduação, me convidou para ser professor juntamente com ele. É um grande prazer!



Existem diversas funções para importar dados para objetos do R, incluindo funções para ler arquivos do excel (xls, ou xlsx), arquivos XML, arquivos *.DBF, etc. O R também tem pacotes que interagem diretamente com bancos de dados (mysql, postgressql, etc.). Não iremos cobrir esses tipos aqui, mas você pode pesquisar sozinho no site do R.

É frequente encontrarmos problemas de acentuação e na transferibilidade entre sistemas operacionais diferentes (Mac, Linux, Windows). A palavra chave aqui é Encoding de Caracteres.

Se você usa Windows, e no seu gerenciador de arquivos estes aparecem sem extensão (.csv,.txt,.doc, etc.), mude nas suas preferências para não ocultar extensões de arquivos conhecidos. Dessa forma você consegue ver os arquivos pelo tipo (extensão).

Importando arquivos de texto simples

Muitos dados que obtemos online e os próprios scripts do R são do formato mais simples que existe, que são arquivos de texto, geralmente arquivos salvos com extensões .csv ou .txt. Arquivos desse tipo você pode abrir em qualquer editor de texto e em qualquer sistema operacional e em qualquer versão. Isso garante arquivamento, longevidade e transferibilidade. Portanto, é a melhor forma de salvar seus dados e compartilhar eles.

Qualquer arquivo desse tipo pode ser lido pelos os editores de script do R ou RStudio. Pode também exportar planilhas do Excel ou BR-Libre-Open-Offices para esse formato.

É importante atentar em arquivos de texto contendo dados tabulados para:

  • O separador das colunas pode ser ;, “tabulação” (no R = \t), “vírgula”, qualquer símbolo que indique a separação das colunas (ou seja não está nas células).

  • Casas decimais podem ser . ou ,. Saiba como seus dados estão antes de importar para indicar o delimitador adequado, ou converter, por exemplo, usando gsub().

  • Datas - colunas com datas constituem um objeto de classe “date” no R, que a converte em número que pode ser usado em operações matemáticas. Dependendo de como seus dados estão formatados no original, é comum inversão de mês com dia entre, por exemplo, o sistema inglês (MM-DD-YYYY) e o sistema português (DD-MM-YYYY). Tenha controle disso.

Por isso, recomenda-se que:

  • Defina um padrão que você sempre usará para formatar teus dados ANTES de importá-los ao R. Dessa forma você irá memorizar rapidamente como importar os dados do jeito que você sempre prepara;

  • Padronize o Encoding (UTF8 é padrão Mac e Linux; Latin1 é padrão Windows) em arquivos TXT;

  • Padronize a decimal (ponto ou vírgula?);

  • Pradonize a quebra de Linha, i.e., o que indica no texto o início de uma nova linha (novamente diferente entre Mac, Linux e Windows);

  • Padronize se colunas de texto vão entre aspas;

  • Padronize como você dá nome às colunas - nome de colunas e de linhas não devem ser muito longos. Evite acentos e espaços em branco em nomes de colunas;

  • Se você usa planilha, recomendamos usar uma versão de software livre da família BR-Libre-Open-Office, pois na hora de exportar um "*.csv" você tem total controle sobre o “Encoding” e sobre a formatação do arquivo em geral. Tanto para ler como para salvar arquivos de planilhas.

Exemplo

Pacote base
  • read.table() - esta é a principal função que você irá usar para importar seus dados no R. Ela funciona para importar arquivos em formato de texto simples (.csv, .txt).

  • http://www.botanicaamazonica.wiki.br/labotam/lib/exe/fetch.php?media=disciplinas:bot89_2013:exercicio08:municipiosbrasil.csv - vamos usar este arquivo como exemplo, que contém as coordenadas geográficas dos municípios brasileiros. Baixe o arquivo para sua pasta de trabalho.

  • Abra o arquivo com um editor de texto simples (Bloco de Notas, Notepad++, TextWrangler, Gedit, etc.) e veja como está formatado:

    • Qual o separador de colunas? (é tabulação, como seu editor mostra isso);
    • Qual o Encoding dos caracteres? (consegue ver e editar isso no seu editor?);
    • Qual a quebra de linha? (consegue ver e editar isso no seu editor?
    • Aspas duplas ou simples definem colunas? (não tem nenhuma aspas!)
    • Abra o arquivo no BR-Libre-OpenOffice de sua preferência:
      • Veja os controles na importação quanto aos elementos acima
      • Salve o arquivo como *.ods
      • Salve novamente como *.csv - veja como você tem controle na exportação quanto aos elementos acima.
# se você colocou o arquivo na sua pasta de trabalho, ele deve estar visível por
dir(pattern = "csv")
# então posso ler sem precisar especificar o caminho até o arquivo

# veja o help da função antes de começar
?read.table
# os seguintes argumentos são mais importantes:
# sep = " " #o codigo que separa as colunas, o padrão é espaço
# quote = "\"'"  #o que define células de texto - o padrão é interpretar tanto aspa simples como dupla presentes
# dec = "." #ponto é a casa decimal padrão
# header = FALSE #a primeira linha não tem o nome de colunas
# as.is = FALSE #o padrão é converter texto em fatores, se usar T não fará isso
# na.strings #se definir, pode informar aqui que símbolos em células inteiras que sejam interpretados como valores ausentes (NA)
# encoding #codificação da acentuação. o padrão é 'unknown' (desconhecido), na qual ele reconhece segundo o sistema operacional. As opções mais usadas são 'latin1' ou 'utf8' e alterne com isso se você tem problemas com acentos.

# o arquivo original tem os seguintes formatos:
# colunas separadas por tabulação (no R isso é definido pela expressão regular "\t")
# decimal com ponto
# não tem aspas definindo as colunas de texto.
# a primeira linha é o nome das colunas.
# Então, para ler posso usar:
dd <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T)
class(dd) # data.frame
dim(dd) # dimensão do objeto
head(dd) # cabeçalho do data.frame

# veja o que aconteceria se eu achasse que no meu arquivo as colunas são separadas por vírgula
dd2 <- read.table(file = "municipiosbrasil.csv", sep = ",", header = T)
head(dd2)
dim(dd2) # apenas 1 coluna, porque o separador informado não é o mesmo dos dados

# e se o encoding do meu arquivo estiver errado?
dd3 <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T, encoding = "latin1")
dd3[5562, ] # veja o que aconteceu com os acentos nessa linha
dd[5562, ] # no original o encoding não é "latin1"

# veja a estrutura do objeto correto
str(dd)
# Poxa, todas as colunas são fatores, mesmo as colunas Latitude e Longitude que são numéricas.
# Deve ter algum valor nessas colunas que não são numéricos.
# Quais são?
vl <- is.na(as.numeric(as.vector(dd$Latitude))) # quais são NA quando eu converto para numérico? Pois esses devem ser valores de texto e não numéricos. Note que converti o fator para vetor antes de converter para numérico. A função is.na pergunta o que é NA, pois os textos que não podem ser convertidos para número serão valores ausentes (NA)
sum(vl)
dd[vl, ] # essas linhas tem a palavra "NULL" para Latitude e Longitude no arquivo original (volte lá para confirmar), e o R não reconheceu isso como ausente NA. Como vetores devem ser da mesma classe, os números dessas colunas foram codificados como texto e as colunas convertidas a fatores de texto que é o padrão da função read.table()

# podemos usar o argumento na.strings para corrigir isso durante a importação
dd4 <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T, dec = ".", na.strings = c("NULL", "NA", ""))
# qualquer CELULA INTEIRA que contenha NULL ou NA ou esteja vazia SERÁ INTERPRETADA COMO VALOR AUSENTE e codificada como NA no R.
str(dd4)
# note que agora as colunas Latitude e Longitude foram interpretadas como número

# mas o que acontece se informamos mal a casa decimal?
dd5 <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T, dec = ",", na.strings = c("NULL", "NA", ""))
str(dd5)
# como tem ponto como definição de casa decimal no arquivo de dados, as colunas numéricas foram novamente interpretadas como texto.

# Texto como vetores ou fatores?
dd4 <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T, dec = ".", na.strings = c("NULL", "NA", ""))
str(dd4) # todas as colunas de texto neste objeto foram interpretadas como fatores
# o argumento as.is permite corrigir isso. "as is" significa "como está" nos dados originais, então valores de texto são lidos como vetores de caracteres não codificados em fatores.
dd6 <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T, dec = ".", na.strings = c("NULL", "NA", ""), as.is = TRUE)
str(dd6) # diferentemente do objeto anterior, não há mais fatores

# Lembram que colocamos o endereco do arquivo mais acima?
# podemos usar um endereco da internet para baixar um arquivo
dd7 <- read.table("http://www.botanicaamazonica.wiki.br/labotam/lib/exe/fetch.php?media=disciplinas:bot89_2013:exercicio08:municipiosbrasil.csv", sep = "\t", header = TRUE)
dd7
head(dd7)
# a função read.table tem vários outros argumentos. Veja o help e entenda isso bem.
Pacote readr
  • read_delim - principal função para ler arquivos do pacote readr. Funciona de maneira parecida com o read.table com algumas pequenas diferenças: não converte colunas de texto que possam ser categorizadas em fatores (read.table faz isso por padrão), retorna um tibble no lugar de um data.frame (tibbles são data.frames diferentes na maneira como aparecem no console; além de mostrar apenas uma porção dos dados, para cada coluna há a indicação do tipo de variável presente), assume por padrão que o dado importado possui cabeçalho. Existem outras diferenças que podem ser melhor entendidas no site do pacote: https://github.com/tidyverse/readr. Os argumentos possuem nomes diferentes do que os utilizados em read.table e, como este, importa arquivos em formato de texto simples (.csv , .txt).
# pacote readr
# usando como exemplo o mesmo arquivo municipiosbrasil.csv
install.packages("readr", dependencies = TRUE)
library("readr")
rr1 <- read_delim("municipiosbrasil.csv", delim = "\t")
rr1
dd7
dim(rr1)
dim(dd7)
rr2 <- read_delim("http://www.botanicaamazonica.wiki.br/labotam/lib/exe/fetch.php?media=disciplinas:bot89_2013:exercicio08:municipiosbrasil.csv", delim = "\t")
rr2
Pacote data.table
  • fread - principal função para ler arquivos do pacote data.table. Este pacote é muito conhecido devido à velocidade de suas ações, funcionando perfeitamente para dados grandes. Esta função possui uma particularidade: o usuário não precisa indicar o separador; automaticamente ele descobre o separador e lê o arquivo. Em casos especiais, é necessário a indicação do separador com o argumento sep, igual ao read.table. Ao ler um arquivo, a função retorna também um data.frame, porém com certas particularidas quanto à impressão do resultado na tela do console, como acontece com a função read_delim do pacote readr. Mais informações, leiam atentamente o site do pacote: https://github.com/Rdatatable/data.table. O pacote como um todo é uma excelente ferramenta na manipulação de dados. Como os pacotes citados acima, esta função é capaz de importar arquivos em formato de texto simples (.csv , .txt).
# pacote data.table
# usando como exemplo o mesmo arquivo municipiosbrasil.csv
install.packages("data.table", dependencies = TRUE)
library("data.table")
dt1 <- fread("municipiosbrasil.csv")
dt1
dt2 <- fread("http://www.botanicaamazonica.wiki.br/labotam/lib/exe/fetch.php?media=disciplinas:bot89_2013:exercicio08:municipiosbrasil.csv")
dt2

Importando o Excel diretamente

Os principais erros aqui podem ser por células unidas, cabeçalhos no topo da planilha, e acentos. Veja o Help das funções usadas para parametros opcionais para resolver isso.

# instale o pacote
install.packages("readxl", dependencies = TRUE)

# leia o pacote
library("readxl") # tidyverse

# se o arquivo for xls
# Salve o arquivo municipiosbrasil.csv como xlsx ou xls
meuxlsx <- "municipiosbrasil.xlsx"
dd <- read_excel(path = meuxlsx, sheet = 1)
dd
dd <- as.data.frame(dd)
dd

# se o arquivo for xls
meuxls <- "municipiosbrasil.xls"
dd <- read_excel(path = meuxls, sheet = 1)
dd
dd <- as.data.frame(dd)
dd

Exportando Dados

Pacote base
  • write.table() é a principal função que você irá usar para exportar seus dados do R. Ela funciona para exportar arquivos em formato de texto simples (.csv, .txt) e usa basicamente os mesmos argumentos da função read.table().
?write.table # veja o help - recomendo usar essa função genérica e evitar de usar atalhos tipo write.csv, que no fundo usam esta mesma função

# vamos usar o mesmo arquivo
dir(pattern = "csv")
# ler o arquivo para o R para ter algo a exportar
dd <- read.table(file = "municipiosbrasil.csv", sep = "\t", header = T, dec = ".", na.strings = c("NULL", "NA", ""), as.is = TRUE)
str(dd) # diferentemente do objeto anterior, não há mais fatores

# filtrando apenas para municipios do Amazonas:
vl <- dd$Province %in% "Amazonas"
sum(vl) # quantos são?
# ou, desse jeito que é identico:
vl <- dd$Province == "Amazonas"
sum(vl)
dd.am <- dd[vl, ]
nrow(dd.am) == sum(vl) # deve ser verdadeiro, certo?

# salvando esses dados num novo arquivo com diferentes formatações:
# separado por tabulação e textos sem aspas e células NA sem nada
write.table(dd.am, file = "muni-am1.csv", sep = "\t", na = "", quote = FALSE)
# separado por tabulação e textos com aspas e células NA sem nada
write.table(dd.am, file = "muni-am2.csv", sep = "\t", na = "", quote = TRUE)

# separado por vírgula e textos com aspas e células NA com a palavra valor.ausente
write.table(dd.am, file = "muni-am3.csv", sep = ",", na = "valor.ausente", quote = TRUE)

# separado por vírgula e textos com aspas e células NA vazios e não adicona nomes das linhas como primeira coluna (row.names=FALSE). Pode deslocar a primeira linha na sua planilha SE você NAO USAR este argumento)
write.table(dd.am, file = "muni-am4.csv", sep = ",", na = "", quote = TRUE, row.names = FALSE)

# separado por tabulação e textos sem aspas e células NA vazias, sem nomes das linhas, e quebra de linha no formato do windows (eol = "\r\n")
write.table(dd.am, file = "muni-am5.csv", sep = ",", na = "", quote = TRUE, row.names = FALSE, eol = "\r\n")

# ABRA OS ARQUIVOS GERADOS NO SEU EDITOR DE TEXTO E COMPARE AS FORMATAÇÕES GERADAS
Pacote readr
  • write_delim - principal função do pacote readr para exportar data.frames em formato de texto simples (.csv, .txt) e usa basicamente os mesmos argumentos da função read_delim, pertencente ao mesmo pacote.
# exportando dados com pacote readr
# utilizando mesmo objeto criado com pacote base

write_delim(dd.am, "muni-am6.csv", delim = "\t")
write_delim(dd.am, "muni-am7.csv", delim = ";")
Pacote data.table
  • fwrite - principal função do pacote data.table para exportar data.frames em formato de texto simples (.csv, .txt) e usa basicamente os mesmos argumentos da função read_delim, pertencente ao mesmo pacote.
# exportando dados com pacote data.table
# utilizando mesmo objeto criado com pacote base
fwrite(dd.am, "muni-am8.csv", sep = "\t")

Outras funções úteis

scan() - lê um arquivo de texto em qualquer formato para um vetor ou lista no R. Função genérica que bom conhecer.

# vamos usar o mesmo arquivo
dir(pattern = "csv")
# esta função é muito util para ler linha por linha um arquivo de texto que você quer explorar.
dd <- scan(file = "municipiosbrasil.csv", what = "complex", sep = "\n")
class(dd)
length(dd) # cada linha é um elemento do vetor
dd[1]
# usando tabulação
dd2 <- scan(file = "municipiosbrasil.csv", what = "complex", sep = "\t")
class(dd2)
length(dd2) # cada célula é um elemento deste vetor
dd2[1:5]

# nao faz muito sentido com esses dados que tem formato de tabela, mas essa função pode ser usada com qualquer arquivo de tipo texto, por exemplo:
# de um artigo no qual você quer buscar palavras e tabular palavras chaves?
# num log de uma análise feita por outro software (nao no R) do qual você quer extrair resultados a partir da lógica complicada do texto de resultado)
# etc.

Relacionados