write.table schreibt unerwünschte führende leere Spalten in den Header, wenn Rownamen vorhanden sind

89

Überprüfen Sie dieses Beispiel:

> 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

Die Tabelle wird korrekt angezeigt. Es gibt zwei verschiedene Möglichkeiten, es in eine Datei zu schreiben ...

write.csv(a, 'a.csv') was wie erwartet gibt:

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

und write.table(a, 'a.txt')was vermasselt

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

in der Tat fehlt eine leere Lasche ... was für nachgeschaltete Dinge ein Schmerz im Hintern ist. Ist das ein Fehler oder eine Funktion? Gibt es eine Problemumgehung? (anders als write.table(cbind(rownames(a), a), 'a.txt', row.names=FALSE)

Prost, Yannick

Yannick Wurm
quelle

Antworten:

136

Zitieren ?write.table, Abschnitt CSV-Dateien :

Standardmäßig gibt es keinen Spaltennamen für eine Spalte mit Zeilennamen. Wenn col.names = NAund row.names = TRUEein leerer Spaltenname hinzugefügt wird, ist dies die Konvention, die verwendet wird, damit CSV-Dateien von Tabellenkalkulationen gelesen werden.

Also musst du tun

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

und du bekommst

"" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
Marek
quelle
4
@Marek, wäre es möglich, der Spalte "Rownames" einen Namen hinzuzufügen? Dh statt "" "ID" oder ähnliches hinzufügen?
Dnaiel
2
@Dnaiel Soweit ich weiß, kannst du nicht. Sie können Zeilennamen mit Daten verknüpfen und ihnen Namen geben (wie in Frage).
Marek
1
@rusalkaguy Deine Bearbeitung hat keinen Sinn. Diese "Erweiterung" ist in der ursprünglichen Frage ("Problemumgehung außer")
Marek
Wie würden Sie die Nummer in jeder Spalte unter den Spaltennamen anordnen lassen?
rrs
@rrs Du meinst Format mit fester Breite? Schauen Sie sich write.fwf aus dem gdata-Paket an . Und stellen Sie eine neue Frage anstelle eines Kommentars. Und warum brauchst du das jemals?!
Marek
10

Eine geringfügige Änderung an der sehr hilfreichen Antwort von @Marek fügt der Spalte "Rownames" einen Header hinzu: Fügen Sie die Rownames vorübergehend als erste Spalte im data.frame hinzu und schreiben Sie diese, wobei Sie die tatsächlichen Rownames ignorieren.

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

und du bekommst

"H" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
rusalkaguy
quelle
Sie sollten Mareks Antwort so bearbeiten, dass sie dies enthält, denke ich.
user8397947
3

Für alle, die in der tidyverse arbeiten (dplyr usw.), kann die rownames_to_column()Funktion aus dem tibble- Paket verwendet werden, um row.names einfach in eine Spalte zu konvertieren, z.

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

Wenn Sie dies mit der row.names=FALSEOption in write.table()kombinieren, erhalten Sie eine Ausgabe mit Kopfzeilennamen für alle Spalten.

Keith Hughitt
quelle
1

Für diejenigen, die das gleiche Problem beim Speichern einer Matrix mit haben write.table()und die Spalte row.names beibehalten möchten, gibt es tatsächlich eine äußerst einfache Lösung:

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

Auf diese Weise bringen Sie die write.tableFunktion dazu, eine Kopfzeilenbezeichnung für die Spalte row.names zu erstellen. Die resultierende CSV-Datei würde folgendermaßen aussehen:

row_name_col;val1_col;val2_col
row1;1;4 
row2;2;5 
row3;3;6 
uribalb
quelle
Ich versuche col.names = c ("Zeilenname", Spaltennamen (Matrix)) und erhalte eine Fehlermeldung mit der Angabe einer ungültigen 'col.names'-Spezifikation. Irgendeine Idee was falsch ist? c ("Zeilenname", Spaltennamen (Matrix)) gibt den richtigen Text an.
MichaelE
write.tableErwarten Sie einen Header mit einer Länge ncol(matrix)und Sie geben ihm noch einen. Ich habe die obige Lösung ausprobiert, sie funktioniert nicht. Am besten verschieben Sie die Rownamen wie in anderen Lösungen als Spalte
aurelien
0

Ich habe eine einfache Funktion von @mnel überarbeitet, die durch die Verwendung von Verbindungen mehr Flexibilität bietet. Hier ist die Funktion:

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

Sie können die Funktion 'write.table', 'write.csv', 'write.delim' usw. angeben.

Prost!

yuanhangliu1
quelle