write.table scrive una colonna vuota iniziale indesiderata nell'intestazione quando ha rownames


90

controlla questo esempio:

> 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

la tabella viene visualizzata correttamente. Esistono due modi diversi per scriverlo su file ...

write.csv(a, 'a.csv') che dà come previsto:

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

e write.table(a, 'a.txt')che rovina

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

in effetti, manca una scheda vuota .... che è una seccatura per le cose a valle. È un bug o una funzionalità? C'è una soluzione alternativa? (diverso da write.table(cbind(rownames(a), a), 'a.txt', row.names=FALSE)

Salute, yannick

Risposte:


137

Citando ?write.table, sezione file CSV :

Per impostazione predefinita, non esiste un nome di colonna per una colonna di nomi di riga. Se col.names = NAe row.names = TRUEviene aggiunto un nome di colonna vuoto, che è la convenzione utilizzata per i file CSV da leggere dai fogli di calcolo.

Quindi devi farlo

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

e ottieni

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

4
@Marek, sarebbe possibile aggiungere un nome alla colonna Rownames? Cioè, invece di "", aggiungi "ID" o qualcosa di simile?
Dnaiel

2
@Dnaiel Da quello che so che non puoi. Puoi associare i nomi delle righe ai dati e dare loro dei nomi (come nella domanda).
Marek

1
@rusalkaguy La tua modifica non ha senso. Questa "estensione" è nella domanda originale ("soluzione alternativa diversa da")
Marek

Come faresti allineare il numero in ogni colonna sotto i nomi delle colonne?
RRS

@rrs Intendi formato a larghezza fissa? Guarda write.fwf dal pacchetto gdata . E fai una nuova domanda invece di commentare. E perché mai ne hai bisogno ?!
Marek

10

Una leggera modifica alla risposta molto utile di @Marek aggiungerà un'intestazione alla colonna rownames: aggiungi temporaneamente i rownames come prima colonna nel data.frame e scrivilo, ignorando i rownames reali.

> 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 ottieni

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

Dovresti modificare la risposta di Marek per includerla, penso.
user8397947

3

Per chiunque lavori nel tidyverse (dplyr, ecc.), La rownames_to_column()funzione del pacchetto tibble può essere utilizzata per convertire facilmente row.names in una colonna, ad esempio:

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

Combinando questo con l' row.names=FALSEopzione nei write.table()risultati in output con i nomi di intestazione per tutte le colonne.


1

Per coloro che riscontrano lo stesso problema durante il salvataggio di una matrice con write.table()e desiderano mantenere la colonna row.names, in realtà esiste una soluzione estremamente semplice:

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

In questo modo stai sostanzialmente ingannando la write.tablefunzione per creare un'etichetta di intestazione per la colonna row.names. Il file .csv risultante sarebbe simile a questo:

row_name_col;val1_col;val2_col
row1;1;4 
row2;2;5 
row3;3;6 

Sto provando col.names = c ("row_name", colnames (matrix)) e ricevo un errore che dice che la specifica "col.names" non è valida. Qualche idea su cosa sia sbagliato? c ("row_name", colnames (matrix)) fornisce il testo corretto.
MichaelE

write.tableaspettati un'intestazione di lunghezza ncol(matrix)e ne stai dando un'altra. Ho provato la soluzione sopra, non funziona, la cosa migliore è spostare i rownames come una colonna come in altre soluzioni
aurelien

0

Ho rivisto una semplice funzione di @mnel, che aggiunge flessibilità utilizzando le connessioni. Ecco la funzione:

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,...)
}

Puoi specificare che la funzione sia "write.table", "write.csv", "write.delim" ecc.

Saluti!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.