2011-10-25 11 views
8

Puedo usar read.csv o read.csv2 para leer datos en R. Pero el problema que encontré es que mi separador es una cadena de múltiples bytes en lugar de un solo carácter. ¿Cómo puedo lidiar con esto?¿Cómo leer un archivo de texto en GNU R con un separador de múltiples bytes?

+1

¿Cuál es su cadena de bytes múltiples? – jthetzel

+0

Creo que si nos fijamos en los argumentos read.table() y sep más generales, puede usar una cadena de múltiples bytes. – mweylandt

+0

@mweylandt Creo que 'read.table()' 's' sep' solo acepta bytes individuales (lo mismo para 'scan()'). – jthetzel

Respuesta

9

Proporcionar datos de ejemplo ayudaría. Sin embargo, es posible que pueda adaptar lo siguiente a sus necesidades.

creé un ejemplo de archivo de datos, que es un simplemente un archivo de texto que contiene lo siguiente:

1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 

Me guardé como 'test.csv'. El carácter de separación es la cadena 'sep'. Creo que read.csv() usa scan(), que solo acepta un solo carácter para sep. Para conseguir alrededor de él, tenga en cuenta lo siguiente:

dat <- readLines('test.csv') 
dat <- gsub("sep", " ", dat) 
dat <- textConnection(dat) 
dat <- read.table(dat) 

readLines() simplemente lee las líneas de gsub sustituye la cadena de separación de múltiples caracteres para un único ' ', o lo que es conveniente para sus datos.. Luego, textConnection() y read.data() lo lee todo cómodamente. Para conjuntos de datos más pequeños, esto debería estar bien. Si tiene datos muy grandes, considere preprocesar con algo como AWK para sustituir la cadena de separación de caracteres múltiples. Lo anterior es de http://tolstoy.newcastle.edu.au/R/e4/help/08/04/9296.html.

actualización En cuanto a su comentario, si tiene espacios en sus datos, utilizar un separador de sustitución diferente. Considere cambiar a test.csv:

1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 

Entonces, con la siguiente función:

readMulti <- function(x, sep, replace, as.is = T) 
{ 
    dat <- readLines(x) 
    dat <- gsub(sep, replace, dat) 
    dat <- textConnection(dat) 
    dat <- read.table(dat, sep = replace, as.is = as.is) 

    return(dat) 
} 

Probar:

readMulti('test.csv', sep = "sep", replace = "\t", as.is = T) 

Aquí, vuelva a colocar el separador original con pestañas (\t). El as.is se pasa al read.table() para evitar que las cadenas que se leen sean factores, pero esa es su decisión. Si usted tiene un espacio en blanco más complicado dentro de sus datos, es posible encontrar el argumento quote en read.table() útiles, o pre-proceso con AWK, Perl, etc.

Algo similar con crippledlambda de strsplit() más probable es equivalente para los datos de tamaño moderado. Si el rendimiento se convierte en un problema, pruebe ambos y vea cuál funciona para usted.

+0

read.table recibirá el mismo mensaje de error.La sugerencia de jthetzel suena como buena. En realidad, aprovecho awk para procesar los datos en bruto antes de leerlos en R. Pero la pregunta aquí es cómo podemos tratar con el personaje en el nuevo carácter de separación después de gsub (Digamos que tenemos un ' 'dentro del valor en su código de muestra). – RobinMin

+0

@RobinMin Pruebe con un separador de repuesto diferente por actualización anterior. – jthetzel

3

En este caso puede reemplazar textConnection(txt) con su nombre de archivo, pero esencialmente puede construir un código o función alrededor de strsplit. Aquí estoy suponiendo que tiene una línea de cabecera, pero se puede dar por supuesto definir un argumento header y generalizar la creación de su trama de datos en base a la siguiente función:

> read.multisep <- function(File,sep) { 
+ Lines <- readLines(File) 
+ Matrix <- do.call(rbind,strsplit(Lines,sep,fixed=TRUE)) 
+ DataFrame <- structure(data.frame(Matrix[-1,]),names=Matrix[1,]) ## assuming header is present 
+ DataFrame[] <- lapply(DataFrame,type.convert)     ## automatically convert modes 
+ DataFrame 
+ } 
> 
> example <- "a#*&b#*&c 
+ 1#*&2#*&3 
+ 4#*&5#*&6" 
> 
> read.multisep(textConnection(example),sep="#*&") 
    a b c 
1 1 2 3 
2 4 5 6 
+0

read.multisep funciona bien para mí ~! Gracias @jthetzel – RobinMin

Cuestiones relacionadas