Livelli di fattore non visti quando si aggiungono nuovi record con valori di stringa non visti a un frame di dati, causare Avviso e generare NA

StackOverflow https://stackoverflow.com/questions/1632772

  •  06-07-2019
  •  | 
  •  

Domanda

Ho un dataframe (14,5K righe per 15 colonne) contenente i dati di fatturazione dal 2001 al 2007.

Vi allego nuovi dati del 2008 con: alltime <- rbind(alltime,all2008)

Purtroppo questo genera un avvertimento:

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

La mia ipotesi è che ci siano alcuni nuovi pazienti i cui nomi non erano nel precedente frame di dati e quindi non saprebbero quale livello dare a quelli. Allo stesso modo nuovi nomi invisibili nella colonna "medico di riferimento".

Qual è la soluzione?

È stato utile?

Soluzione

Potrebbe essere causato dalla mancata corrispondenza dei tipi in due data.frames.

Prima di tutto i tipi di controllo (classi). A fini diagnostici, procedere come segue:

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

Mi aspetto che ci sia una riga simile a:

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

In tal caso, quindi spiegazione: rbind non verificare la corrispondenza dei tipi. Se analizzi rbind.data.frame codice, potresti vedere che il primo argomento ha inizializzato i tipi di output. Se nel primo tipo data.frame è presente un fattore, la colonna output data.frame è un fattore con livelli unique(c(levels(x1),levels(x2))). Ma quando nella seconda colonna data.frame non è presente il fattore levels(x2) è NULL, quindi i livelli non si estendono.

Significa che i tuoi dati di output sono sbagliati! Esistono NA valori anziché valori reali

Suppongo che:

  1. crei i tuoi vecchi dati con un'altra versione di R / RODBC, quindi i tipi sono stati creati con metodi diversi (impostazioni diverse - separatore decimale forse)
  2. ci sono NULL o alcuni dati specifici nella colonna problematica, ad es. qualcuno cambia colonna nel database.

Soluzione:

trova la colonna sbagliata e trova la ragione per cui è sbagliata e corretta. Elimina la causa non i sintomi.

Altri suggerimenti

Un " facile " il modo è semplicemente di non impostare le stringhe come fattori durante l'importazione di dati di testo.

Nota che le funzioni read.{table,csv,...} accettano un parametro stringsAsFactors, che è impostato di default su TRUE. Puoi impostarlo su FALSE mentre stai importando e rbind - i tuoi dati.

Se desideri impostare la colonna come fattore alla fine, puoi farlo anche tu.

Ad esempio:

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)

1) crea il frame di dati con stringsAsFactor impostato su FALSE. Questo dovrebbe risolvere il problema dei fattori

2) in seguito non usare rbind - incasina i nomi delle colonne se il frame di dati è vuoto. fallo semplicemente in questo modo:

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

Come suggerito nella risposta precedente, leggi le colonne come carattere ed esegui la conversione in fattori dopo rbind. SQLFetch (Suppongo che RODBC ) abbia anche l'argomento stringsAsFactors o as.is per controllare la conversione dei caratteri. I valori consentiti sono read.table, ad es. as.is=TRUE o alcuni numeri di colonna.

Ho avuto lo stesso problema con i tipi non corrispondenti, soprattutto con i fattori. Ho dovuto incollare insieme due set di dati altrimenti compatibili.

La mia soluzione è convertire i fattori in entrambi i frame di dati in " carattere " ;. Quindi funziona come un incantesimo :-)

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

Se si desidera visualizzare i tipi nei due frame di dati eseguiti (cambiare i nomi var):

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

Quando si crea il frame di dati, è possibile scegliere di rendere i fattori delle colonne di stringhe (stringsAsFactors=T) o di mantenerli come stringhe.

Nel tuo caso, non creare fattori per le colonne di stringhe. Conservali come stringhe, quindi l'aggiunta funziona correttamente. Se alla fine hai bisogno che siano fattori, esegui tutti gli inserimenti e le aggiunte prima come stringa, quindi convertili in fattore.

Se crei i fattori delle colonne stringa e poi aggiungi le righe che contengono valori invisibili, ricevi l'errore che hai citato su ogni nuovo livello di fattore invisibile e quel valore viene sostituito con NA ...

> df <- data.frame(patient=c('Ann','Bob','Carol'), referring_doctor=c('X','Y','X'), stringsAsFactors=T)

  patient referring_doctor
1     Ann                X
2     Bob                Y
3   Carol                X

> df <- rbind(df, c('Denise','Z'))
Warning messages:
1: In `[<-.factor`(`*tmp*`, ri, value = "Denise") :
  invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, ri, value = "Z") :
  invalid factor level, NA generated
> df
  patient referring_doctor
1     Ann                X
2     Bob                Y
3   Carol                X
4    <NA>             <NA>

Quindi non rendere i fattori delle colonne di stringa. Conservali come stringhe, quindi l'aggiunta funziona correttamente :

> df <- data.frame(patient=c('Ann','Bob','Carol'), referring_doctor=c('X','Y','X'), stringsAsFactors=F)
> df <- rbind(df, c('Denise','Z'))
  patient referring_doctor
1     Ann                X
2     Bob                Y
3   Carol                X
4  Denise                Z

Per modificare il comportamento predefinito :

options(stringsAsFactors=F)

Per convertire singole colonne in / da stringa o fattore

df$col <- as.character(df$col)
df$col <- as.factor(df$col)

ecco una funzione per prendere i nomi di riga comuni di 2 frame di dati e fare un rbind dove fondamentalmente troviamo i campi che sono fattori, aggiungiamo i nuovi fattori e poi facciamo il rbind. Questo dovrebbe occuparsi di qualsiasi problema:

rbindCommonCols < -function (x, y) {

commonColNames = intersect(colnames(x), colnames(y))
x = x[,commonColNames]
y = y[,commonColNames]

colClassesX = sapply(x, class)
colClassesY = sapply(y, class)
classMatch = paste( colClassesX, colClassesY, sep = "-" )
factorColIdx = grep("factor", classMatch)

for(n in factorColIdx){ 
    x[,n] = as.factor(x[,n])
    y[,n] = as.factor(y[,n])
}

for(n in factorColIdx){ 
    x[,n] = factor(x[,n], levels = unique(c( levels(x[,n]), levels(y[,n]) )))
    y[,n] = factor(y[,n], levels = unique(c( levels(y[,n]), levels(x[,n]) )))  
} 

res = rbind(x,y)
res

}

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top