write.table écrit indésirables conduisant à la colonne vide-tête quand a rownames
-
21-09-2019 - |
Question
vérifier 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 affiche correctement. Il y a deux façons différentes d'écrire 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 se visse vers le haut
"A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
En effet, un onglet vide manque .... qui est une douleur dans le cul pour des 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
)
Cordialement, Yannick
La solution
Invoquant ?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
etrow.names = TRUE
un blanc nom de colonne est ajouté, qui est la convention pour les fichiers CSV être lu par des feuilles de calcul.
Vous devez donc 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
Autres conseils
Une légère modification @Marek très utile réponse ajouterez un en-tête à la colonne rownames:. Ajouter temporairement les rownames comme la première colonne du data.frame et écrire que, en ignorant les vrais 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)
et vous obtenez
"H" "A" "B" "C"
"A" 1 4 7
"B" 2 5 8
"C" 3 6 9
Pour tous ceux qui travaillent dans le tidyverse (dplyr, etc.), la fonction rownames_to_column()
de la paquet de Tibble peut être utilisé pour convertir facilement row.names à 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
En combinant ceci avec l'option row.names=FALSE
dans les résultats de write.table()
en sortie avec des noms d'en-tête pour toutes les colonnes.
Pour ceux qui connaissent le même problème lors de l'enregistrement d'une matrice avec write.table()
et veulent garder la colonne row.names, il est 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 duper essentiellement la fonction write.table
dans la création d'une étiquette d'en-tête pour la colonne row.names. Le fichier .csv obtenu ressemblerait à ceci:
row_name_col;val1_col;val2_col
row1;1;4
row2;2;5
row3;3;6
Je révisais une simple fonction de @mnel, ce 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 la fonction d'être 'write.table', 'write.csv', 'write.delim' etc.
Vive!