write.table zapisuje niechciane początkowe puste kolumny do nagłówka, gdy ma rownames

91

sprawdź ten przykład:

> 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

tabela wyświetla się poprawnie. Istnieją dwa różne sposoby zapisania go do pliku ...

write.csv(a, 'a.csv') co daje zgodnie z oczekiwaniami:

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

i write.table(a, 'a.txt')który schrzanił

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

w istocie brakuje pustej zakładki ... co jest utrapieniem dla dalszych rzeczy. Czy to błąd czy funkcja? Czy jest w pobliżu praca? (inne niż write.table(cbind(rownames(a), a), 'a.txt', row.names=FALSE)

Pozdrawiam, yannick

Yannick Wurm
źródło

Odpowiedzi:

140

Cytując ?write.table, sekcja pliki CSV :

Domyślnie nie ma nazwy kolumny dla kolumny nazw wierszy. Jeśli col.names = NAi row.names = TRUEzostanie dodana pusta nazwa kolumny, zgodnie z konwencją odczytywania plików CSV przez arkusze kalkulacyjne.

Więc musisz to zrobić

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

i dostajesz

"" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
Marek
źródło
4
@Marek, czy byłoby możliwe dodanie nazwy do kolumny rownames? To znaczy, zamiast „”, dodaj „ID” czy coś podobnego?
Dnaiel
2
@Dnaiel Z tego, co wiem, nie możesz. Możesz powiązać nazwy wierszy z danymi i nadać im nazwy (jak w pytaniu).
Marek
1
@rusalkaguy Twoja zmiana nie ma sensu. To „rozszerzenie” jest w pierwotnym pytaniu („obejście inne niż”)
Marek
Jak możesz ustawić liczbę w każdej kolumnie pod nazwami kolumn?
rrs
@rrs Masz na myśli format o stałej szerokości? Spójrz na write.fwf z pakietu gdata . I zadaj nowe pytanie zamiast komentarza. I dlaczego kiedykolwiek tego potrzebujesz ?!
Marek
10

Niewielka modyfikacja bardzo pomocnej odpowiedzi @Marek BĘDZIE dodała nagłówek do kolumny rownames: tymczasowo dodaj rownames jako pierwszą kolumnę w data.frame i zapisz to, ignorując prawdziwe rownames.

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

i dostajesz

"H" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
rusalkaguy
źródło
Myślę, że powinieneś zredagować odpowiedź Marka, aby to uwzględnić.
user8397947
3

Dla każdego, kto pracuje w tidyverse (dplyr itp.), rownames_to_column()Funkcja z pakietu tibble może być użyta do łatwej konwersji row.names na kolumnę, np .:

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

Połączenie tego z row.names=FALSEopcją w write.table()daje wynik z nazwami nagłówków dla wszystkich kolumn.

Keith Hughitt
źródło
1

Dla tych, którzy napotykają ten sam problem podczas zapisywania macierzy z write.table()kolumną row.names i chcą ją zachować, istnieje w rzeczywistości niezwykle proste rozwiązanie:

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

Robiąc to, w zasadzie oszukujesz write.tablefunkcję do utworzenia etykiety nagłówka dla kolumny row.names. Wynikowy plik .csv wyglądałby następująco:

row_name_col;val1_col;val2_col
row1;1;4 
row2;2;5 
row3;3;6 
uribalb
źródło
Próbuję col.names = c ("row_name", colnames (matrix)) i otrzymuję błąd informujący o nieprawidłowej specyfikacji "col.names". Masz jakiś pomysł, co jest nie tak? c ("nazwa_wiersza", nazwy kolumn (macierz)) daje poprawny tekst.
MichaelE
write.tableoczekuj nagłówka długości ncol(matrix)i dajesz mu jeszcze jeden. Wypróbowałem powyższe rozwiązanie, nie działa, najlepiej przesuwać rownames jako kolumnę jak w innych rozwiązaniach
aurelien
0

Poprawiłem prostą funkcję z @mnel, która dodaje elastyczności poprzez używanie połączeń. Oto funkcja:

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

Możesz określić funkcję jako „write.table”, „write.csv”, „write.delim” itd.

Twoje zdrowie!

yuanhangliu1
źródło