write.table grava coluna vazia inicial indesejada no cabeçalho quando tem nomes de domínio

90

verifique este exemplo:

> a = matrix(1:9, nrow = 3, ncol = 3, dimnames = list(LETTERS[1:3], LETTERS[1:3]))
> a
  A B C
A 1 4 7
B 2 5 8
C 3 6 9

a tabela é exibida corretamente. Existem duas maneiras diferentes de gravá-lo em um arquivo ...

write.csv(a, 'a.csv') que dá como esperado:

"","A","B","C"
"A",1,4,7
"B",2,5,8
"C",3,6,9

e write.table(a, 'a.txt')que bagunça

"A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9

na verdade, uma guia vazia está faltando ... o que é uma dor de cabeça para as coisas posteriores. isso é um erro ou uma característica? Existe uma solução alternativa? (diferente de write.table(cbind(rownames(a), a), 'a.txt', row.names=FALSE)

Saúde, yannick

Yannick Wurm
fonte

Respostas:

137

Citando ?write.table, seção de arquivos CSV :

Por padrão, não há nome de coluna para uma coluna de nomes de linha. Se col.names = NAe row.names = TRUEum nome de coluna em branco for adicionado, que é a convenção usada para arquivos CSV a serem lidos em planilhas.

Então você deve fazer

write.table(a, 'a.txt', col.names=NA)

e você consegue

"" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
Marek
fonte
4
@Marek, seria possível adicionar um nome na coluna rownames? Ou seja, em vez de "", adicione "ID" ou algo semelhante?
Dnaiel de
2
@Dnaiel Pelo que eu sei, você não pode. Você pode vincular nomes de linhas com dados e dar-lhes nomes (como na pergunta).
Marek
1
@rusalkaguy Sua edição não tem sentido. Esta "extensão" está em questão original ("solução alternativa diferente de")
Marek
Como você faria com que o número em cada coluna fosse alinhado com os nomes das colunas?
rrs
@rrs Você quer dizer formato de largura fixa? Veja write.fwf do pacote gdata . E faça uma nova pergunta em vez de comentar. E por que você precisa disso ?!
Marek
10

Uma pequena modificação na resposta do @Marek muito útil VAI adicionar um cabeçalho à coluna rownames: adicione temporariamente os rownames como a primeira coluna no data.frame e escreva isso, ignorando os nomes reais.

> a = matrix(1:9, nrow = 3, ncol = 3, dimnames = list(LETTERS[1:3], LETTERS[1:3]))
> write.table(data.frame("H"=rownames(a),a),"a.txt", row.names=FALSE)

e você consegue

"H" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
Rusalkaguy
fonte
Você deve editar a resposta de Marek para incluir isso, eu acho.
user8397947
3

Para quem trabalha no tidyverse (dplyr, etc.), a rownames_to_column()função do tibble pacote pode ser usada para converter facilmente row.names em uma coluna, por exemplo:

library('tibble')
a = as.data.frame(matrix(1:9, nrow=3, ncol=3, 
                  dimnames=list(LETTERS[1:3], LETTERS[1:3])))

a %>% rownames_to_column('my_id')

  my_id A B C
1     A 1 4 7
2     B 2 5 8
3     C 3 6 9

Combinar isso com a row.names=FALSEopção em write.table()resulta na saída com nomes de cabeçalho para todas as colunas.

Keith Hughitt
fonte
1

Para aqueles que enfrentam o mesmo problema ao salvar uma matriz write.table()e desejam manter a coluna row.names, há uma solução extremamente simples:

 write.table(matrix,file="file.csv",quote=F,sep=";", row.names=T
             col.names=c("row_name_col;val1_col","val2_col"))

Ao fazer isso, você está basicamente enganando a write.tablefunção para criar um rótulo de cabeçalho para a coluna row.names. O arquivo .csv resultante ficaria assim:

row_name_col;val1_col;val2_col
row1;1;4 
row2;2;5 
row3;3;6 
uribalb
fonte
Estou tentando col.names = c ("row_name", colnames (matriz)) e recebo um erro dizendo especificação inválida de 'col.names'. Alguma idéia do que está errado? c ("row_name", colnames (matriz)) fornece o texto correto.
MichaelE
write.tableespere um cabeçalho de comprimento ncol(matrix)e você está dando mais um. Eu tentei a solução acima, ela não funciona, o melhor é mover os rownames como uma coluna como em outras soluções
aurelien
0

Eu revisei uma função simples de @mnel, que adiciona flexibilidade usando conexões. Aqui está a função:

my.write <- function(x, file, header, f = write.csv, ...){
# create and open the file connection
datafile <- file(file, open = 'wt')
# close on exit 
on.exit(close(datafile))
# if a header is defined, write it to the file (@CarlWitthoft's suggestion)
if(!missing(header)) {
writeLines(header,con=datafile, sep='\t')
writeLines('', con=datafile, sep='\n')
}
# write the file using the defined function and required addition arguments  
f(x, datafile,...)
}

Você pode especificar a função como 'write.table', 'write.csv', 'write.delim' etc.

Felicidades!

yuanhangliu1
fonte