web-dev-qa-db-fra.com

write.table écrit une colonne vide non désirée dans l'en-tête quand a des noms de domaine

vérifiez cet exemple:

> 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

le tableau s'affiche correctement. Il existe deux façons différentes de l'écrire dans un fichier ...

write.csv(a, 'a.csv') qui donne comme prévu:

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

et write.table(a, 'a.txt') qui fout

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

en effet, il manque un onglet vide .... ce qui est pénible pour les choses en aval. Est-ce un bug ou une fonctionnalité? Y at-il un travail autour? (autre que write.table(cbind(rownames(a), a), 'a.txt', row.names=FALSE)

À la vôtre, yannick

80
Yannick Wurm

En citant ?write.table, section fichiers CSV:

Par défaut, il n'y a pas de nom de colonne pour une colonne de noms de ligne. Si col.names = NA et row.names = TRUE un nom de colonne vide est ajouté, qui est la convention utilisée pour que les fichiers CSV soient lus par des feuilles de calcul.

Donc tu dois faire

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

et vous obtenez

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

Une légère modification de @Marek, une réponse très utile, ajoutera un en-tête à la colonne des noms de domaine: ajoutez temporairement les noms de famille comme première colonne dans le data.frame, et écrivez cela, en ignorant les vrais noms de famille.

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

et vous obtenez

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

Pour toute personne travaillant dans le tidyverse (dplyr, etc.), la fonction rownames_to_column() du paquet tibble peut être utilisée pour convertir facilement row.names en une colonne, par exemple:

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

La combinaison de cela avec l'option row.names=FALSE Dans write.table() entraîne une sortie avec des noms d'en-tête pour toutes les colonnes.

3
Keith Hughitt

Pour ceux qui rencontrent le même problème lors de l'enregistrement d'une matrice avec write.table() et qui souhaitent conserver la colonne row.names, il existe en fait une solution extrêmement simple:

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

En faisant cela, vous trompez essentiellement le write.table fonction dans la création d'une étiquette d'en-tête pour la colonne row.names. Le fichier .csv résultant ressemblerait à ceci:

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

J'ai révisé une fonction simple de @mnel, qui ajoute de la flexibilité en utilisant des connexions. Voici la fonction:

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

Vous pouvez spécifier que la fonction est 'write.table', 'write.csv', 'write.delim' etc.

À votre santé!

0
yuanhangliu1