tablas str funcion extraer exploracion datos data contar columnas r dataframe append r-factor levels

extraer - funcion str en r



Niveles de factor ocultos al anexar nuevos registros con valores de cadena invisibles a un marco de datos, causan Advertencia y dan como resultado NA (7)

Tengo un gran marco de datos (14552 filas por 15 columnas) que contiene datos de facturación de 2001 a 2007. He usado sqlFetch para obtener datos de 2008. Para agregar los datos de 2008 a los datos de los 7 años anteriores, uno haría lo siguiente:

alltime <- rbind(alltime,all2008)

Lamentablemente eso genera

Mensaje de advertencia: En [<-.factor ( *tmp* , ri, value = c (NA, NA, NA, NA, NA, NA, NA,: nivel de factor no válido, NA generadas)

Mi suposición es que hay algunos pacientes nuevos cuyos nombres no estaban en el marco de datos anterior y, por lo tanto, no sabrían a qué nivel darlos. De manera similar, nuevo nombre no visto en la columna del médico referente.

La forma en que R importa datos y automáticamente resuelve lo que es numérico y lo que no (y por lo tanto lo convierte en un factor) es maravilloso, hasta que tenga que manipularlo más y luego se convierta en un dolor. ¿Cómo supero mi problema elegantemente?


1) crea el marco de datos con stringsAsFactor establecido en FALSE. Esto debería resolver el problema del factor

2) después no use rbind - confunde los nombres de las columnas si el marco de datos está vacío. simplemente hazlo de esta manera:

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 se sugirió en la respuesta anterior, lea las columnas como carácter y realice la conversión a factores después de rbind . SQLFetch (supongo que RODBC ) tiene también stringsAsFactors o el argumento as.is para controlar la conversión de caracteres. Los valores permitidos son los de read.table , por ejemplo, as.is=TRUE o algún número de columna.


Cuando crea el marco de datos, tiene la opción de hacer que sus columnas de cadena sean factores ( stringsAsFactors=T ) o mantenerlas como cadenas.

Para su caso, no haga factores de columnas de cadena. Guárdelos como cuerdas, luego anexar funciona bien. Si los necesita para que finalmente sean factores, realice toda la inserción y agregue primero como cadena, y finalmente conviértalos en factor.

Si define los factores de columnas de cadena y luego agrega filas que contienen valores no vistos, obtendrá el error que mencionó en cada nuevo nivel de factor no visto y ese valor se reemplaza 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>

Así que no hagas que tus columnas de cadena sean factores. Guárdelos como cadenas, luego anexar funciona bien :

> 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 cambiar el comportamiento predeterminado :

options(stringsAsFactors=F)

Para convertir columnas individuales a / desde cadena o factor

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


Podría deberse a una falta de coincidencia de tipos en dos data.frames .

En primer lugar, compruebe los tipos (clases). Para fines de diagnóstico, haga esto:

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

Espero que haya una fila como esta:

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

Si es así, explicación: rbind no verifica que los tipos coincidan. Si analiza el código rbind.data.frame , entonces puede ver que el primer argumento inicializó los tipos de salida. Si en el primer tipo data.frame es un factor, la columna output data.frame es un factor con niveles unique(c(levels(x1),levels(x2))) . Pero cuando en la segunda columna data.frame no es factor, entonces los levels(x2) son NULL , por lo que los niveles no se extienden.

¡Significa que tus datos de salida son incorrectos! Hay NA en lugar de valores verdaderos

Supongo que:

  1. usted crea sus datos viejos con otra versión de R / RODBC, por lo que los tipos se crearon con diferentes métodos (diferentes configuraciones - separador decimal tal vez)
  2. hay NULL o algunos datos específicos en la columna problemática, ej. alguien cambia de columna en la base de datos.

Solución:

encuentra la columna incorrecta y encuentra la razón por la que está mal y está arreglada. Elimina la causa, no los síntomas.


Tuve el mismo problema con los desajustes de tipo, especialmente con los factores. Tuve que unir dos conjuntos de datos compatibles.

Mi solución es convertir los factores en ambos dataframes en "personaje". Entonces funciona como un 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) }

Si desea ver los tipos en sus dos marcos de datos ejecutar (cambiar los nombres de var):

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


Una manera "fácil" es simplemente no tener sus cadenas configuradas como factores al importar datos de texto.

Tenga en cuenta que las funciones read.{table,csv,...} toman un parámetro stringsAsFactors , que está configurado por defecto en TRUE . Puede establecer esto en FALSE mientras está importando y rbind sus datos.

Si desea establecer que la columna sea un factor al final, puede hacerlo también.

Por ejemplo:

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)


aquí hay una función para tomar los nombres de fila comunes de 2 marcos de datos y hacer un rbind donde básicamente encontramos los campos que son factores, agregamos los nuevos factores y luego hacemos el rbind. Esto debería encargarse de cualquier problema de factor:

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

}