66 votes

Niveaux de facteurs non perçus lors de l'ajout de nouveaux enregistrements avec des valeurs de chaîne non perçues à un cadre de données, ce qui entraîne un avertissement et le résultat est NA.

J'ai un cadre de données (14,5K lignes par 15 colonnes) contenant des données de facturation de 2001 à 2007.

J'y ajoute les nouvelles données de 2008 avec : alltime <- rbind(alltime,all2008)

Malheureusement, cela génère un avertissement :

> Warning message:
In `[<-.factor`(`*tmp*`, ri, value = c(NA, NA, NA, NA, NA, NA, NA,  :
  invalid factor level, NAs generated

Je pense qu'il y a de nouveaux patients dont les noms ne figuraient pas dans la trame de données précédente et qu'il ne saurait donc pas quel niveau leur attribuer. Il en va de même pour les nouveaux noms non vus dans la colonne "médecin référent".

Quelle est la solution ?

6 votes

C'est étrange. Les facteurs ne devraient pas causer cela, en aidant à rbind est indiqué : "Les facteurs ont leurs niveaux étendus si nécessaire" (R-2.9.2). Peut-être pourriez-vous vérifier exactement quelle colonne provoque ce problème ?

1 votes

Quelle bonne remarque Marek ! Le message d'avertissement m'a fait peur. Après avoir lu votre commentaire, je suis retourné explorer mes données. Toutes les nouvelles données semblent être là et des niveaux supplémentaires ont été ajoutés. À ce stade, je pourrais simplement le laisser comme un avertissement à ignorer - ce qui est une habitude dangereuse à prendre (car il faut alors garder dans sa tête une base de données des avertissements à prendre au sérieux par rapport aux avertissements à ignorer). Comment puis-je déterminer l'origine du message d'avertissement ?

0 votes

"La façon dont R importe les données et détermine automatiquement ce qui est numérique et ce qui ne l'est pas (et en fait ainsi un facteur)..." voir read.csv(..., stringsAsFactors=FALSE y options(stringsAsFactors=FALSE) . Il y a beaucoup de questions sur le SO.

30voto

Marek Points 18000

Cela peut être dû à une incompatibilité entre les types de deux produits. data.frames .

Tout d'abord, vérifiez les types (classes). Faites ceci à des fins de diagnostic :

new2old <- rbind( alltime, all2008 ) # this gives you a warning
old2new <- rbind( all2008, alltime ) # this should be without warning

cbind(
    alltime = sapply( alltime, class),
    all2008 = sapply( all2008, class),
    new2old = sapply( new2old, class),
    old2new = sapply( old2new, class)
)

Je m'attends à ce qu'il y ait une rangée qui ressemble à ça :

            alltime  all2008   new2old  old2new
...         ...      ...       ...      ...
some_column "factor" "numeric" "factor" "character"
...         ...      ...       ...      ...

Si oui, alors l'explication : rbind ne vérifiez pas les correspondances entre les types. Si vous analysez rbind.data.frame alors vous pouviez voir que le premier argument initialisait les types de sortie. Si le premier type de data.frame est un facteur, alors la colonne de data.frame de sortie est un facteur avec des niveaux. unique(c(levels(x1),levels(x2))) . Mais si dans le deuxième cadre de données la colonne n'est pas un facteur alors levels(x2) es NULL pour que les niveaux ne s'étendent pas.

Cela signifie que vos données de sortie sont erronées ! Il y a NA au lieu des valeurs réelles

Je suppose que oui :

  1. vous avez créé vos anciennes données avec une autre version de R/RODBC et les types ont été créés avec des méthodes différentes (différents paramètres - séparateur décimal peut-être).
  2. il y a des NULL ou des données spécifiques dans une colonne problématique, par exemple si quelqu'un change la colonne dans la base de données.

Solution :

trouver la colonne erronée et trouver la raison pour laquelle elle est erronée et la réparer. Éliminez la cause et non les symptômes.

1 votes

Yip. Vous avez raison. Dans un cadre de données, la classe d'une colonne était un facteur et dans un autre, c'était un numérique. Cela a beaucoup perturbé les choses. J'ai converti le numérique en facteur et tout est rentré dans l'ordre. Je vous remercie pour votre aide. Il y avait également d'autres divergences. Par exemple, la divergence entre le facteur et le caractère n'a pas causé de problème.

0 votes

Vous avez raison au sujet du facteur-caractère, quelque part dans le code j'ai trouvé que les niveaux pour cette combinaison sera unique(c(levels(x1),x2)) . Une chose : la combinaison facteur-caractère conduit à un facteur, la combinaison caractère-facteur à un caractère. Donc c'est mieux quand les types correspondent.

27voto

Steve Lianoglou Points 3792

Une méthode "simple" consiste à ne pas définir vos chaînes de caractères comme facteurs lors de l'importation de données textuelles.

Notez que le read.{table,csv,...} Les fonctions prennent un stringsAsFactors qui, par défaut, a pour valeur TRUE . Vous pouvez régler ce paramètre sur FALSE pendant que vous importez et rbind -de vos données.

Si vous souhaitez que la colonne soit un facteur à la fin, vous pouvez également le faire.

Par exemple :

alltime <- read.table("alltime.txt", stringsAsFactors=FALSE)
all2008 <- read.table("all2008.txt", stringsAsFactors=FALSE)
alltime <- rbind(alltime, all2008)
# If you want the doctor column to be a factor, make it so:
alltime$doctor <- as.factor(alltime$doctor)

9voto

Raffael Points 5837

1) créer le cadre de données avec stringsAsFactor réglé sur FALSE. Cela devrait résoudre le problème de facteur

2) par la suite, n'utilisez pas rbind - cela perturbe les noms des colonnes si le cadre de données est vide. faites-le simplement de cette façon :

df[nrow(df)+1,] <- c("d","gsgsgd",4)

/

> df <- data.frame(a = character(0), b=character(0), c=numeric(0))

> df[nrow(df)+1,] <- c("d","gsgsgd",4)

Warnmeldungen:
1: In `[<-.factor`(`*tmp*`, iseq, value = "d") :
  invalid factor level, NAs generated
2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") :
  invalid factor level, NAs generated

> df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F)

> df[nrow(df)+1,] <- c("d","gsgsgd",4)

> df
  a      b c
1 d gsgsgd 4

4voto

rcs Points 22112

Comme suggéré dans la réponse précédente, lisez les colonnes comme des caractères et faites la conversion en facteurs après rbind . SQLFetch (Je suppose que RODBC ) a également le stringsAsFactors ou le as.is pour contrôler la conversion des caractères. Les valeurs autorisées sont les mêmes que pour read.table par exemple, as.is=TRUE ou un numéro de colonne.

3voto

JSawyer Points 106

J'ai eu le même problème avec les incompatibilités de type, en particulier avec les facteurs. J'ai dû coller ensemble deux ensembles de données autrement compatibles.

Ma solution consiste à convertir les facteurs des deux cadres de données en "caractère". Ensuite, cela fonctionne à merveille :-)

    convert.factors.to.strings.in.dataframe <- function(dataframe)
    {
        class.data  <- sapply(dataframe, class)
        factor.vars <- class.data[class.data == "factor"]
        for (colname in names(factor.vars))
        {
            dataframe[,colname] <- as.character(dataframe[,colname])
        }
        return (dataframe)
    }

Si vous voulez voir les types dans vos deux dataframes, exécutez (changez les noms des var) :

    cbind("orig"=sapply(allSurveyData, class), 
          "merge" = sapply(curSurveyDataMerge, class),
          "eq"=sapply(allSurveyData, class) == sapply(curSurveyDataMerge, class)
    )

3 votes

mydf[sapply(mydf, is.factor)] <- lapply(mydf[sapply(mydf, is.factor)], as.character) semble être une approche plus simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X