níveis de fatores invisíveis ao anexar novos registros com valores de cadeia invisíveis a uma trama de dados, causa de aviso e resultado em NA

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

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu tenho uma trama de dados (linhas 14.5K por 15 colunas) contendo faturamento dados de 2001 a 2007.

I acrescentar dados novos 2008 a ele com: alltime <- rbind(alltime,all2008)

Infelizmente isso gera um aviso:

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

Meu palpite é que existem alguns novos pacientes cujos nomes não estavam na trama de dados anterior e, portanto, não saberia o nível para dar aqueles. Da mesma forma novos nomes invisíveis na coluna 'referindo médico'.

Qual é a solução?

Foi útil?

Solução

Pode ser causada por incompatibilidade de tipos em dois data.frames.

Primeiro de todos os tipos de verificação (classes). Para fins de diagnóstico fazer isso:

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

Eu espero que haja uma fileira parece com:

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

Se sim, então a explicação: rbind não verificar os tipos de correspondência. Se você analisar o código rbind.data.frame então você pode ver que o primeiro argumento inicializado tipos de saída. Se em primeiro tipo data.frame é um factor, seguida coluna data.frame saída é fator com níveis unique(c(levels(x1),levels(x2))). Mas quando na segunda coluna data.frame não é fator então levels(x2) é NULL, então os níveis não se estendem.

Isso significa que os dados de saída são errado! Há NA é em vez de valores verdadeiros

Suponho que:

  1. você cria-lo dados antigos com outro R / versão RODBC assim tipos foram criados com métodos diferentes (diferentes configurações - separador decimal talvez)
  2. existem NULL de ou alguns dados específicos na coluna problemática, por exemplo. alguém mudar de coluna sob banco de dados.

Solução:

encontrar coluna errada e achar razão pela qual a sua de errado e fixa. Eliminar a causa Não sintomas.

Outras dicas

Um "fácil" maneira é simplesmente não ter suas cordas definido como fatores ao importar dados de texto.

Note que as funções read.{table,csv,...} ter um parâmetro stringsAsFactors, que é pelo conjunto padrão para TRUE. Você pode definir isso para FALSE enquanto você está importando e rbind-ing seus dados.

Se você gostaria de definir a coluna para ser um fator no final, você pode fazer isso também.

Por exemplo:

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) criar o quadro de dados com stringsAsFactor definido para FALSE. Isto deve resolver o fator-issue

2) depois não use rbind - ele mexe-se os nomes das colunas, se o quadro de dados está vazio. simplesmente fazê-lo desta maneira:

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

Como sugerido na resposta anterior, leia as colunas como personagem e fazer a conversão a fatores após rbind. SQLFetch (presumo RODBC ) também tem o stringsAsFactors ou o argumento as.is para controlar a conversão de caracteres. Os valores permitidos são como para read.table, por exemplo, ou algum número as.is=TRUE coluna.

Eu tive o mesmo problema com descasamentos tipo, especialmente com fatores. Eu tive que cola juntos dois conjuntos de dados de outra forma compatíveis.

A minha solução é converter fatores em ambos os dataframes de "caráter". Em seguida, ele funciona como um encanto: -)

    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 você quiser ver os tipos em seus dois dataframes executar (nomes mudança var):

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

Ao criar a trama de dados você tem a opção de fazer seus fatores colunas de cordas (stringsAsFactors=T), ou mantê-los como strings.

Para o seu caso, não faça seus fatores de colunas de cordas. Mantê-los como cordas, em seguida, acrescentando funciona bem. Se você precisa deles para ser, em última instância fatores, fazer tudo a inserção e anexando primeiro como corda, em seguida, finalmente convertê-los em fator.

Se você fizer os fatores colunas de cordas e, em seguida, linhas anexar contendo valores invisíveis, você recebe o erro que você mencionou em cada novo nível fator invisível e esse valor é substituído por 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>

Assim não fazem seus fatores de colunas de cordas. Mantê-los como cordas, em seguida, acrescentando funciona bem :

> 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

Para alterar o comportamento padrão :

options(stringsAsFactors=F)

Para converter colunas individuais para / de corda ou fator

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

aqui está uma função para tirar os nomes de linha comuns de 2 quadros de dados e fazer uma rbind onde nós basicamente encontrar os campos que estão fatores, adicionar os novos fatores, em seguida, fazer o rbind. Isso deve cuidar de quaisquer questões relacionadas com factores:

rbindCommonCols <-função (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

}

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top