Menu

Gravar Dados em Arquivos no R (write.csv, saveRDS)

Exportando do R: write.csv com row.names = FALSE (sempre), write.table para outros delimitadores e saveRDS para viagens de ida e volta que não perdem seus tipos.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

write.csv() Exporta um Data Frame

Tirar um data frame do R e colocá-lo em um arquivo que outros programas conseguem abrir é uma chamada:

write.csv(df, "results.csv", row.names = FALSE)

Essa é a linha para memorizar - incluindo o row.names = FALSE, que justificaremos em um instante. O primeiro argumento é o data frame, o segundo é o nome do arquivo, e a função não retorna nada: seu trabalho inteiro é o efeito colateral de criar o arquivo.

Você pode ver exatamente o que o write.csv() produz sem tocar no disco, porque ele aceita qualquer conexão onde espera um nome de arquivo - incluindo stdout(), que apenas imprime:

Eis o seu CSV: uma linha de cabeçalho, uma linha por registro, valores de texto entre aspas, números sem elas. (As aspas são o padrão quote = TRUE; todo leitor de CSV convencional lida com elas, então deixe como está.) Gravar em um arquivo de verdade é a mesma chamada com "results.csv" no lugar de stdout().

Por Que row.names = FALSE Deve Ser Seu Padrão

Todo data frame carrega nomes de linha - geralmente só os números 1, 2, 3... - e o padrão do write.csv() é gravá-los no arquivo como uma primeira coluna extra com cabeçalho vazio. Veja como fica a saída padrão, e o que acontece quando esse arquivo faz a viagem de volta para o R:

A exportação ganhou uma primeira coluna sem nome contendo "1", "2" - e na reimportação o read.csv() teve de chamá-la de alguma coisa, então inventou X. Essa é a coluna misteriosa X que intriga todo iniciante: não é dado, é a numeração de linhas do R vazando para o seu arquivo. Repita isso algumas vezes num ciclo de exporta-importa e você acumula X, X.1, X.2...

Nomes de linha quase nunca carregam informação real - e quando carregam, a informação pertence a uma coluna de verdade de qualquer forma. Então torne row.names = FALSE um reflexo. Ele deveria, discutivelmente, ser o padrão; não é, por razões de retrocompatibilidade, então o hábito fica por sua conta.

Onde o Arquivo Vai Parar

write.csv(df, "results.csv") grava no diretório de trabalho do R - e se ele não for onde você esperava, o arquivo parece desaparecer. Ele não falhou; está apenas na pasta que getwd() imprime. É a mesma armadilha da leitura, em imagem espelhada, e as mesmas duas ferramentas a resolvem:

getwd()                          # the folder your file went to
write.csv(df, "C:/Users/ada/results/out.csv", row.names = FALSE)   # or: remove all doubt

Caminhos completos (barras normais funcionam em toda plataforma, inclusive Windows) tornam os scripts inequívocos. Como o diretório de trabalho é definido e gerenciado está em diretório de trabalho.

write.table() para Outros Delimitadores - e a Questão do Append

O write.csv() é, na verdade, um invólucro fino sobre o write.table() de propósito geral, pré-configurado para vírgulas. Chame write.table() diretamente quando precisar de outro formato - mais comumente separado por tabulação:

Separado por tabulação, sem aspas - o formato que muitas ferramentas seguintes preferem. Repare que com write.table() você define tudo explicitamente; ele não herda a vírgula nem as aspas padrão do write.csv.

Uma coisa que o write.csv() se recusa a fazer é append: passar append = TRUE rende um aviso de que a opção foi ignorada, porque anexar reescreveria a linha de cabeçalho no meio do arquivo. Se você genuinamente precisa adicionar linhas a um CSV existente - digamos, registrando resultados entre execuções - desça ao write.table() e suprima o cabeçalho você mesmo:

write.table(new_rows, "log.csv", sep = ",",
            append = TRUE, col.names = FALSE, row.names = FALSE)

E se você está no tidyverse, readr::write_csv(df, "out.csv") é a contraparte do read_csv(): mesma saída, mais rápido em data frames grandes, e ele nunca grava nomes de linha - um argumento a menos para lembrar.

saveRDS() e readRDS(): Round-Trips Exatos

CSV é um formato com perdas. Ele armazena texto, e ponto final - então uma coluna Date vira a string "2026-08-07", um factor vira seus rótulos com a ordenação de níveis perdida, atributos somem, e cada tipo precisa ser adivinhado de novo na importação (geralmente com acerto, às vezes não - zeros à esquerda, estamos olhando para vocês). E um CSV só comporta uma tabela retangular: um modelo ajustado, uma lista, uma matriz com dimnames não têm representação alguma em CSV.

Quando o arquivo é para o R - salvar os dados limpos de hoje para a sessão de amanhã - pule os formatos de texto por completo:

saveRDS(df, "clean_data.rds")        # today

df <- readRDS("clean_data.rds")      # tomorrow: identical object, types intact

saveRDS() serializa um objeto do R, qualquer objeto, exatamente. readRDS() o devolve byte a byte: factors mantêm seus níveis, datas continuam datas, nada é adivinhado de novo. Funciona com qualquer coisa - um data frame, uma lista de data frames, um modelo de regressão ajustado. O arquivo .rds é binário comprimido, então costuma ser menor que o CSV também. O único custo é que nada além do R consegue abri-lo - que é precisamente o motivo da regra prática: CSV para compartilhar com humanos e outras ferramentas, RDS para guardar para você mesmo.

save() e load() - e Por Que o RDS Costuma Vencer

Você também vai encontrar um par mais antigo. save() grava vários objetos nomeados em um único arquivo .RData, e load() os restaura - no seu workspace, com os nomes originais:

save(df, model, params, file = "session.RData")
load("session.RData")    # df, model, params silently appear

Essa conveniência é o problema. Quem decide os nomes das variáveis é o load(), não você - ele planta objetos no seu ambiente sem você ver, sobrescrevendo silenciosamente qualquer coisa que já tivesse aqueles nomes. Seis meses depois, ninguém lembra o que session.RData sequer contém sem carregá-lo para descobrir.

readRDS() tem a interface honesta: você escolhe o nome (df <- readRDS(...)), nada é sobrescrito pelas suas costas, e um arquivo significa um objeto. A menos que você precise especificamente empacotar vários objetos em um único arquivo, prefira RDS. (Se precisar de um pacote, colocar os objetos em uma lista nomeada e passar a lista ao saveRDS() dá o mesmo efeito sem nenhuma das surpresas.)

O Que Você Leva

  • write.csv(df, "out.csv", row.names = FALSE) - a exportação inteira, e sim, sempre com o row.names = FALSE.
  • A coluna misteriosa X na reimportação são os nomes de linha vazando para o arquivo; o padrão os gravou, você não deveria.
  • Os arquivos vão para o diretório de trabalho - getwd() encontra exportações "perdidas", caminhos completos as previnem.
  • write.table() lida com outros delimitadores e (com col.names = FALSE) com append de verdade; write.csv() deliberadamente não anexa.
  • saveRDS() / readRDS() fazem o round-trip exato de qualquer objeto do R - tipos, factors, atributos intactos. CSV para compartilhar, RDS para você.
  • Prefira RDS a save()/load(): nomes explícitos, sem sobrescritas silenciosas.

A seguir: um tipo de dado que merece a própria página antes de te morder numa importação - datas.

Perguntas frequentes

Como exporto um data frame para CSV no R?

write.csv(df, "output.csv", row.names = FALSE). A parte do row.names = FALSE importa: sem ela, o R grava seus números de linha internos como uma primeira coluna extra, que aparece como uma coluna misteriosa chamada X quando alguém reimporta o arquivo.

Por que meu CSV exportado tem uma coluna X quando eu o leio de volta?

Porque o padrão do write.csv é row.names = TRUE - ele gravou os números das linhas como uma primeira coluna sem nome, e o read.csv batizou essa coluna de X na volta. Exporte com row.names = FALSE e a coluna fantasma desaparece.

Qual é a diferença entre write.csv e saveRDS no R?

write.csv produz uma tabela em texto puro que qualquer um pode abrir, mas armazena apenas texto - níveis de factor, tipos Date, atributos e objetos não tabulares são achatados ou perdidos, e os tipos precisam ser adivinhados de novo na importação. saveRDS armazena um objeto do R byte a byte; readRDS o devolve exatamente como era. Use CSV para compartilhar com outros, RDS para guardar para suas próprias sessões de R.

Onde o write.csv salva o arquivo?

No diretório de trabalho atual do R, a menos que você informe um caminho completo. Rode getwd() para ver onde é - se seu arquivo parece ter sumido, ele está na pasta que o getwd() imprime. Passar um caminho completo como "C:/Users/ada/results/out.csv" elimina a ambiguidade.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR