web-dev-qa-db-fra.com

Pourquoi est-ce que j'obtiens X. dans les noms de mes colonnes lors de la lecture d'un bloc de données?

J'ai demandé à question à ce sujet il y a quelques mois , et je pensais que la réponse avait résolu mon problème, mais j'ai rencontré de nouveau le problème et la solution n'a pas fonctionné pour moi.

J'importe un CSV:

orders <- read.csv("<file_location>", sep=",", header=T, check.names = FALSE)

Voici la structure de la trame de données:

str(orders)

'data.frame':   3331575 obs. of  2 variables:
 $ OrderID  : num  -2034590217 -2034590216 -2031892773 -2031892767 -2021008573 ...
 $ OrderDate: Factor w/ 402 levels "2010-10-01","2010-10-04",..: 263 263 269 268 301 300 300 300 300 300 ...

Si j'exécute la commande length sur la première colonne, OrderID, j'obtiens ceci:

length(orders$OrderID)
[1] 0

Si j'exécute le length sur OrderDate, il renvoie correctement:

length(orders$OrderDate)
[1] 3331575

Il s'agit d'un copier/coller du head du CSV.

OrderID,OrderDate
-2034590217,2011-10-14
-2034590216,2011-10-14
-2031892773,2011-10-24
-2031892767,2011-10-21
-2021008573,2011-12-08
-2021008572,2011-12-07
-2021008571,2011-12-07
-2021008570,2011-12-07
-2021008569,2011-12-07

Maintenant, si je réexécute le read.csv, Mais que je supprime l'option check.names, La première colonne du dataframe a maintenant un X. au début du nom.

orders2 <- read.csv("<file_location>", sep=",", header=T)

str(orders2)

'data.frame':   3331575 obs. of  2 variables:
 $ X.OrderID: num  -2034590217 -2034590216 -2031892773 -2031892767 -2021008573 ...
 $ OrderDate: Factor w/ 402 levels "2010-10-01","2010-10-04",..: 263 263 269 268 301 300 300 300 300 300 ...

length(orders$X.OrderID)
[1] 3331575

Cela fonctionne correctement.

Ma question est de savoir pourquoi R ajoute un X. au début du nom de la première colonne? Comme vous pouvez le voir dans le fichier CSV, il n'y a pas de caractères spéciaux. Ce devrait être une simple charge. L'ajout de check.names, Tout en important le nom du CSV, empêchera les données de se charger correctement pour que je puisse effectuer l'analyse.

Que puis-je faire pour résoudre ce problème?

Note latérale: Je me rends compte que c'est un mineur - je suis juste plus frustré par le fait que je pense que je charge correctement, mais que je n'obtiens pas le résultat attendu. Je pourrais renommer la colonne en utilisant colnames(orders)[1] <- "OrderID", mais je veux toujours savoir pourquoi elle ne se charge pas correctement.

52
mikebmassey

read.csv() est un wrapper autour de la fonction plus générale read.table(). Cette dernière fonction a l'argument check.names Qui est documenté comme suit:

check.names: logical.  If ‘TRUE’ then the names of the variables in the
         data frame are checked to ensure that they are syntactically
         valid variable names.  If necessary they are adjusted (by
         ‘make.names’) so that they are, and also to ensure that there
         are no duplicates.

Si votre en-tête contient des étiquettes qui ne sont pas valides sur le plan syntaxique, make.names() les remplacera par un nom valide, basé sur le nom non valide, supprimant les caractères non valides et précédant éventuellement X:

R> make.names("$Foo")
[1] "X.Foo"

Ceci est documenté dans ?make.names:

Details:

    A syntactically valid name consists of letters, numbers and the
    dot or underline characters and starts with a letter or the dot
    not followed by a number.  Names such as ‘".2way"’ are not valid,
    and neither are the reserved words.

    The definition of a _letter_ depends on the current locale, but
    only ASCII digits are considered to be digits.

    The character ‘"X"’ is prepended if necessary.  All invalid
    characters are translated to ‘"."’.  A missing value is translated
    to ‘"NA"’.  Names which match R keywords have a dot appended to
    them.  Duplicated values are altered by ‘make.unique’.

Le comportement que vous voyez est entièrement cohérent avec la façon dont read.table() se charge dans vos données. Cela suggère que vous avez des étiquettes syntaxiquement invalides dans la ligne d'en-tête de votre fichier CSV. Notez le point ci-dessus de ?make.names Que ce qui est une lettre dépend des paramètres régionaux de votre système; Le fichier CSV peut inclure un caractère valide que votre éditeur de texte affichera, mais si R ne s'exécute pas dans les mêmes paramètres régionaux, ce caractère peut ne pas y être valide, par exemple?

Je regarderais le fichier CSV et identifierais tous les caractères non-ASCII dans la ligne d'en-tête; il y a peut-être des caractères non visibles (ou des séquences d'échappement; \t?) dans la ligne d'en-tête également. Il peut se passer beaucoup de choses entre lire le fichier avec les noms non valides et l'afficher dans la console, ce qui pourrait masquer les caractères non valides, alors ne prenez pas le fait qu'il ne montre rien de mal sans check.names Comme indiquant que le fichier est OK.

La publication de la sortie de sessionInfo() serait également utile.

69
Gavin Simpson

Je viens de rencontrer ce problème et c'était pour une raison simple. J'avais des étiquettes qui commençaient par un nombre, et R ajoutait un X devant tous. Je pense que R est confondu avec un nombre dans l'en-tête et applique une lettre pour différencier les valeurs.

Donc, "3_in" est devenu "X3_in" etc ... J'ai résolu en basculant le libellé sur "in_3" et les problèmes ont été résolus.

J'espère que ça aidera quelqu'un.

10
Matt Beam

J'ai rencontré un problème similaire et j'ai voulu partager les lignes de code suivantes pour corriger les noms de colonne. Certainement pas parfait, car une programmation propre en coup droit serait mieux, mais peut-être utile comme point de départ pour quelqu'un comme approche rapide et sale. (J'aurais aimé les ajouter comme commentaire à la question de Ryan/la réponse de Gavin, mais ma réputation n'est pas assez élevée, j'ai donc dû poster une réponse supplémentaire - désolé).

Dans mon cas, plusieurs étapes d'écriture et de lecture des données ont produit une ou plusieurs colonnes nommées "X", X.1 ", ... contenant du contenu dans la colonne X et des numéros de ligne dans les colonnes X.1, ...-. Dans mon cas, le contenu de la colonne X doit être utilisé comme nom de ligne et les autres colonnes X.1, ... doivent être supprimées.

Correct_Colnames <- function(df) {

 delete.columns <- grep("(^X$)|(^X\\.)(\\d+)($)", colnames(df), Perl=T)

  if (length(delete.columns) > 0) {

   row.names(df) <- as.character(df[, grep("^X$", colnames(df))])
   #other data types might apply than character or 
   #introduction of a new separate column might be suitable

   df <- df[,-delete.columns]

   colnames(df) <- gsub("^X", "",  colnames(df))
   #X might be replaced by different characters, instead of being deleted
  }

  return(df)
}
7
Manuel Bickel

J'ai résolu un problème similaire en incluant row.names = FALSE comme argument dans la fonction write.csv. write.csv incluait les noms de ligne en tant que colonne sans nom dans le fichier CSV et read.csv nommait cette colonne "X" lors de la lecture du fichier CSV.

3
Tristan