2012-02-01 20 views
5

Tengo un dataframe en R que cargué de un archivo CSV. Una de las variables se llama "Cantidad" y está destinada a contener números positivos y negativos.R - De factor a error numérico o entero

Cuando miré en el marco de datos, el tipo de datos de esta variable se enumera como un factor, y lo necesito en un formato numérico (¿Pero no está seguro de qué tipo - entero - numérico, umm ...?). Entonces, traté de convertirlo a uno de esos dos formatos pero vi un comportamiento interesante.

trama de datos inicial:

str(df) 

Amount  : Factor w/ 11837 levels "","-1","-10",..: 2 2 1664 4 6290 6290 6290 6290 6290 6290 ... 

Como he mencionado anteriormente, vi algo raro cuando traté de convertirlo en tanto numérica como de número entero. Para mostrar esto, he creado esta comparación:

df2 <- data.frame(df$Amount, as.numeric(df$Amount), as.integer(df$Amount)) 

str(df2) 
'data.frame': 2620276 obs. of 3 variables: 
$ df.Amount   : Factor w/ 11837 levels "","-1","-10",..: 2 2 1664 4 6290 6290 6290 6290 6290 6290 ... 
$ as.numeric.df.Amount.: num 2 2 1664 4 6290 ... 
$ as.integer.df.Amount.: int 2 2 1664 4 6290 6290 6290 6290 6290 6290 ... 

> head(df2, 20) 
     df.Amount  as.numeric.df.Amount.  as.integer.df.Amount. 
1    -1       2       2 
2    -1       2       2 
3    -201      1664      1664 
4    -100       4       4 
5    1      6290      6290 
6    1      6290      6290 
7    1      6290      6290 
8    1      6290      6290 
9    1      6290      6290 
10    1      6290      6290 
11    1      6290      6290 
12    1      6290      6290 
13    1      6290      6290 
14    1      6290      6290 
15    1      6290      6290 
16    1      6290      6290 
17    1      6290      6290 
18    2      7520      7520 
19    2      7520      7520 
20    2      7520      7520 

Los as.numeric y as.integer funciones están tomando la variable Monto y hacer algo a ella, pero no saben que es eso. Mi objetivo es hacer que la variable Amount se convierta en un tipo de tipo de datos numéricos para poder realizar sum/mean/etc en él.

¿Qué estoy haciendo incorrectamente que está causando los números extraños, y qué puedo hacer para solucionarlo?

Respuesta

10

La raíz del problema es probable que tenga algún valor funky en su csv importado. Si proviene de Excel, esto no es raro. Puede ser un símbolo de porcentaje, un carácter de "comentario" de Excel o cualquiera de una larga lista de cosas. Me gustaría ver la csv en su editor de elección y ver lo que puede ver.

Aparte de eso, tiene algunas opciones.

read.csv toma un argumento opcional stringsAsFactors que se pueden establecer a FALSE

Un factor se almacena como niveles enteros, que se asignan a los valores. Al convertir directamente con as.numeric que terminan con los niveles entero en lugar de los valores iniciales:

> x<-10:20 
> as.numeric(factor(x)) 
[1] 1 2 3 4 5 6 7 8 9 10 11 
> 

lo contrario vistazo a ?factor:

En particular, as.numeric aplicado a un factor no tiene sentido, y puede suceder por coacción implícita. Para transformar un factor f a aproximadamente sus valores numéricos originales, as.numeric(levels(f))[f] se recomienda y un poco más eficiente que as.numeric(as.character(f)).

Sin embargo, sospecho que esto dará error porque la entrada tiene algo además de un número.

+0

Una vez que la columna en cuestión es un personaje, en lugar de los factores, he sido capaz de encontrar la fuente de este tipo de problemas utilizando con bastante rapidez '' grep' o grepl' a busca posibles sospechosos. – joran

+0

+1 Buena respuesta. Lo amplié un poco en mi respuesta sobre cómo encontrar los valores ofensivos ... – Tommy

+0

Basura en .... Algunas comas deshonestas causaron el problema. Gracias por la asistencia. – mikebmassey

10

@Justin es correcto. He aquí un recorrido sobre cómo encontrar los valores inválidos:

# A sample data set with a weird value ("4%") in it 
d <- read.table(text="A B\n1 2\n3 4%\n", header=TRUE) 
str(d) 
#'data.frame': 2 obs. of 2 variables: 
# $ A: int 1 3 
# $ B: Factor w/ 2 levels "2","4%": 1 2 

as.numeric(d$B) # WRONG, returns 1 2 (the internal factor codes) 

# This correctly converts to numeric 
x <- as.numeric(levels(d$B))[d$B] # 2 NA 

# ...and this finds the offending value(s): 
d$B[is.na(x)] # 4% 

# and this finds the offending row numbers: 
which(is.na(x)) # row 2 

Tenga en cuenta que si el conjunto de datos tiene valores que faltan codificado como algo más que una celda vacía o la cadena "NA", usted tiene que especificar que a read.table:

# Here "N/A" is used instead of "NA"... 
read.table(text="A B\n1 2\n3 N/A\n", header=TRUE, na.strings="N/A") 
1

Soy nuevo aquí pero he estado utilizando este foro para mis consultas.Estaba teniendo un problema similar, pero el siguiente funcionó para mí. Estoy portar datos de archivo txt a trama de datos

data <- read.delim(paste(folderpath,"data.txt",sep=""),header=TRUE,sep="\\",as.is=6) 

Tenga en cuenta que he usado as.is en la columna 6, que tenía los datos numéricos, así como algunos caracteres de basura en algunas filas. Con los puertos as.is los datos como caracteres en la columna 6., a continuación, los siguientes caracteres cambiados en la columna 6 a valores numéricos. todos los valores de basura se convirtieron a NA, que podrían eliminarse más tarde.

data[,6] <- as.numeric(data[,6]) 

Esperanza esto ayuda

Cuestiones relacionadas