¿Cómo se leen los datos cuando algunos números contienen comas como separador de miles?

Tengo un archivo csv donde algunos de los valores numéricos se expresan como cadenas con comas como separador de miles, por ejemplo, "1,513" lugar de 1513 . ¿Cuál es la forma más sencilla de leer los datos en R?

Puedo usar read.csv(..., colClasses="character") , pero luego tengo que quitar las comas de los elementos relevantes antes de convertir esas columnas a numéricas, y no puedo encontrar una forma clara de hacerlo .

No estoy seguro de cómo read.csv interpretará correctamente, pero puede usar gsub para reemplazar "," con "" , y luego convertir la cadena a numeric usando as.numeric :

 y <- c("1,200","20,000","100","12,111") as.numeric(gsub(",", "", y)) # [1] 1200 20000 100 12111 

Esto también fue respondido previamente en R-Help (y en Q2 aquí ).

Alternativamente, puede preprocesar el archivo, por ejemplo con sed en Unix.

Puede hacer que read.table o read.csv hagan esta conversión de forma semiautomática. Primero cree una nueva definición de clase, luego cree una función de conversión y configúrela como un método “como” usando la función setAs de la siguiente manera:

 setClass("num.with.commas") setAs("character", "num.with.commas", function(from) as.numeric(gsub(",", "", from) ) ) 

Luego ejecute read.csv como:

 DF <- read.csv('your.file.here', colClasses=c('num.with.commas','factor','character','numeric','num.with.commas')) 

Quiero usar R en lugar de preprocesar los datos, ya que los hace más fáciles cuando se revisan los datos. Siguiendo la sugerencia de Shane de usar gsub , creo que es lo mejor que puedo hacer:

 x <- read.csv("file.csv",header=TRUE,colClasses="character") col2cvt <- 15:41 x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))}) 

Esta pregunta tiene varios años, pero me encontré con ella, lo que significa que quizás otros lo harán.

La biblioteca / paquete readr tiene algunas características agradables. Una de ellas es una buena forma de interpretar columnas “desordenadas”, como estas.

 library(readr) read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5", col_types = list(col_numeric()) ) 

Esto rinde

Fuente: dataframe local [4 x 1]

  numbers (dbl) 1 800.0 2 1800.0 3 3500.0 4 6.5 

Un punto importante al leer en archivos: o tiene que preprocesar, como el comentario anterior relacionado con sed , o debe procesarlo mientras lee . A menudo, si tratas de arreglar las cosas después del hecho, hay algunas suposiciones peligrosas que son difíciles de encontrar. (Es por eso que los archivos planos son tan malvados en primer lugar).

Por ejemplo, si no hubiera marcado los col_types , habría obtenido esto:

 > read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5") Source: local data frame [4 x 1] numbers (chr) 1 800 2 1,800 3 3500 4 6.5 

(Observe que ahora es un chr ( character ) en lugar de un numeric ).

O, lo que es más peligroso, si fuera lo suficientemente largo y la mayoría de los elementos iniciales no contenían comas:

 > set.seed(1) > tmp <- as.character(sample(c(1:10), 100, replace=TRUE)) > tmp <- c(tmp, "1,003") > tmp <- paste(tmp, collapse="\"\n\"") 

(de modo que los últimos elementos parecen 🙂

 \"5\"\n\"9\"\n\"7\"\n\"1,003" 

¡Entonces encontrarás problemas para leer esa coma en absoluto!

 > tail(read_csv(tmp)) Source: local data frame [6 x 1] 3" (dbl) 1 8.000 2 5.000 3 5.000 4 9.000 5 7.000 6 1.003 Warning message: 1 problems parsing literal data. See problems(...) for more details. 

“Preproceso” en R:

 lines <- "www, rrr, 1,234, ttt \n rrr,zzz, 1,234,567,987, rrr" 

Puede usar readLines en una textConnection . A continuación, elimine solo las comas que están entre los dígitos:

 gsub("([0-9]+)\\,([0-9])", "\\1\\2", lines) ## [1] "www, rrr, 1234, ttt \n rrr,zzz, 1234567987, rrr" 

También es útil saber, pero no directamente relacionado con esta pregunta, que las comas como separadores decimales pueden manejarse mediante read.csv2 (automágicamente) o read.table (con configuración del parámetro 'dec').

Editar: Más tarde descubrí cómo usar colClasses diseñando una nueva clase. Ver:

¿Cómo cargar df con 1000 separador en R como clase numérica?

una solución dplyr que usa mutate_each y pipes

di que tienes lo siguiente:

 > dft Source: local data frame [11 x 5] Bureau.Name Account.Code X2014 X2015 X2016 1 Senate 110 158,000 211,000 186,000 2 Senate 115 0 0 0 3 Senate 123 15,000 71,000 21,000 4 Senate 126 6,000 14,000 8,000 5 Senate 127 110,000 234,000 134,000 6 Senate 128 120,000 159,000 134,000 7 Senate 129 0 0 0 8 Senate 130 368,000 465,000 441,000 9 Senate 132 0 0 0 10 Senate 140 0 0 0 11 Senate 140 0 0 0 

y desea eliminar las comas de las variables de año X2014-X2016 y convertirlas a numéricas. también, digamos que X2014-X2016 se leen como factores (predeterminado)

 dft %>% mutate_each(funs(as.character(.)), X2014:X2016) %>% mutate_each(funs(gsub(",", "", .)), X2014:X2016) %>% mutate_each(funs(as.numeric(.)), X2014:X2016) 

mutate_each aplica la función (es) dentro de funs a las columnas especificadas

Lo hice secuencialmente, una función a la vez (si usas funciones múltiples dentro de funs entonces creas columnas innecesarias adicionales)

Si el número está separado por “.” y decimales por “,” (1.200.000,00) al llamar a gsub debe set fixed=TRUE as.numeric(gsub(".","",y,fixed=TRUE))

Creo que el preprocesamiento es el camino a seguir. Podría usar Notepad ++ que tiene una opción de reemplazar expresiones regulares.

Por ejemplo, si su archivo fue así:

 "1,234","123","1,234" "234","123","1,234" 123,456,789 

Luego, podría usar la expresión regular "([0-9]+),([0-9]+)" y reemplazarla por \1\2

 1234,"123",1234 "234","123",1234 123,456,789 

Entonces podría usar x <- read.csv(file="x.csv",header=FALSE) para leer el archivo.

Una forma muy conveniente es readr::read_delim -family. Tomando el ejemplo de aquí: Importando csv con múltiples separadores en R , puede hacerlo de la siguiente manera:

 txt <- 'OBJECTID,District_N,ZONE_CODE,COUNT,AREA,SUM 1,Bagamoyo,1,"136,227","8,514,187,500.000000000000000","352,678.813105723350000" 2,Bariadi,2,"88,350","5,521,875,000.000000000000000","526,307.288878142830000" 3,Chunya,3,"483,059","30,191,187,500.000000000000000","352,444.699742995200000"' require(readr) read_csv(txt) # = read_delim(txt, delim = ",") 

Lo que resulta en el resultado esperado:

 # A tibble: 3 × 6 OBJECTID District_N ZONE_CODE COUNT AREA SUM       1 1 Bagamoyo 1 136227 8514187500 352678.8 2 2 Bariadi 2 88350 5521875000 526307.3 3 3 Chunya 3 483059 30191187500 352444.7 

Otra solución:

  y <- c("1,200","20,000","100","12,111") as.numeric(unlist(lapply( strsplit(y,","),paste, collapse=""))) 

Sin embargo, será considerablemente más lento que gsub .

No es tan complicado, intente esto: y <- as.numeric (gsub (",", "", as.character (y))) y si solo es una de las columnas, puede subconjuntar con y $ 2 como se muestra y $ 2 <- as.numeric (gsub (",", "", as.character (y $ 2)))

Usando la función read_delim, que es parte de la biblioteca readr , puede especificar un parámetro adicional:

 locale = locale(decimal_mark = ",") read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ",")) 

* El punto y coma en la segunda línea significa que read_delim leerá los valores separados por punto y coma de csv.

Esto ayudará a leer todos los números con una coma como números correctos.

Saludos

Mateusz Kania