Leer archivo de texto de ancho fijo

Estoy intentando cargar este conjunto de datos con formato feo en mi sesión R: http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for

Weekly SST data starts week centered on 3Jan1990 Nino1+2 Nino3 Nino34 Nino4 Week SST SSTA SST SSTA SST SSTA SST SSTA 03JAN1990 23.4-0.4 25.1-0.3 26.6 0.0 28.6 0.3 10JAN1990 23.4-0.8 25.2-0.3 26.6 0.1 28.6 0.3 17JAN1990 24.2-0.3 25.3-0.3 26.5-0.1 28.6 0.3 

Hasta ahora, puedo leer las líneas con

  x = readLines(path) 

Pero el archivo mezcla ‘espacio en blanco’ con ‘-‘ como separadores, y no soy un experto en expresiones regulares. Agradezco cualquier ayuda para convertir esto en un dataframe R agradable y limpio. ¡Gracias!

    Este es un archivo de ancho fijo. Use read.fwf() para leerlo:

     x < - read.fwf( file=url("http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for"), skip=4, widths=c(12, 7, 4, 9, 4, 9, 4, 9, 4)) head(x) V1 V2 V3 V4 V5 V6 V7 V8 V9 1 03JAN1990 23.4 -0.4 25.1 -0.3 26.6 0.0 28.6 0.3 2 10JAN1990 23.4 -0.8 25.2 -0.3 26.6 0.1 28.6 0.3 3 17JAN1990 24.2 -0.3 25.3 -0.3 26.5 -0.1 28.6 0.3 4 24JAN1990 24.4 -0.5 25.5 -0.4 26.5 -0.1 28.4 0.2 5 31JAN1990 25.1 -0.2 25.8 -0.2 26.7 0.1 28.4 0.2 6 07FEB1990 25.8 0.2 26.1 -0.1 26.8 0.1 28.4 0.3 

    Actualizar

    El paquete readr (publicado en abril de 2015) proporciona una alternativa simple y rápida.

     library(readr) x < - read_fwf( file="http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for", skip=4, fwf_widths(c(12, 7, 4, 9, 4, 9, 4, 9, 4))) 

    Comparación de velocidad: readr::read_fwf() fue ~ 2 utils::read.fwf () más rápido que utils::read.fwf () .

    Otra forma de determinar el ancho …

     df < - read.fwf( file=url("http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for"), widths=c(-1, 9, -5, 4, 4, -5, 4, 4, -5, 4, 4, -5, 4, 4), skip=4 ) 

    El argumento -1 en el ancho dice que hay una columna de un carácter que debe ignorarse, el -5 en el argumento de anchos dice que hay una columna de cinco caracteres que debe ignorarse, del mismo modo ...

    ref: https://www.inkling.com/read/r-cookbook-paul-teetor-1st/chapter-4/recipe-4-6

    En primer lugar, esa pregunta es directamente de un curso de Coursera “Obtener datos y limpiarlo” de Leeks. Si bien hay otra parte de la pregunta, la parte difícil es leer el archivo.

    Dicho esto, el curso está destinado principalmente para el aprendizaje.

    Odio el procedimiento de ancho fijo de R. Es lento y para un gran número de variables, rápidamente se convierte en un dolor negar ciertas columnas, etc.

    Creo que es más fácil usar readLines() y luego usar substr() para hacer tus variables

     x < - readLines(con=url("http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for")) # Skip 4 lines x <- x[-(1:4)] mydata <- data.frame(var1 = substr(x, 1, 10), var2 = substr(x, 16, 19), var3 = substr(x, 20, 23), var4 = substr(x, 29, 32) # and so on and so on ) 

    Ahora puede usar la función read_fwf() en el paquete readr Hadley Wickham.

    Es de esperar una gran mejora en el rendimiento, en comparación con la base read.fwf() .

    Aquí documento la lista de alternativas para leer archivos de ancho fijo en R, así como proporcionar algunos puntos de referencia para los que es más rápido.

    Mi enfoque preferido es combinar fread con stringi ; es competitivo como el enfoque más rápido, y tiene el beneficio adicional (IMO) de almacenar sus datos como una data.table datos:

     library(data.table) library(stringi) col_ends < - list(beg = c(1, 10, 15, 19, 23, 28, 32, 36, 41, 45, 49, 54, 58), end = c(9, 14, 18, 22, 27, 31, 35, 40, 44, 48, 53, 57, 61)) data = fread( "http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for", header = FALSE, skip = 4L, sep = NULL )[, lapply(1:(length(col_ends$beg)), function(ii) stri_sub(V1, col_ends$beg[ii], col_ends$end[ii])) ][ , paste0("V", c(2, 5, 8, 11)) := NULL] # V1 V3 V4 V6 V7 V9 V10 V12 V13 # 1: 03JAN1990 23.4 -0.4 25.1 -0.3 26.6 0.0 28.6 0.3 # 2: 10JAN1990 23.4 -0.8 25.2 -0.3 26.6 0.1 28.6 0.3 # 3: 17JAN1990 24.2 -0.3 25.3 -0.3 26.5 -0.1 28.6 0.3 # 4: 24JAN1990 24.4 -0.5 25.5 -0.4 26.5 -0.1 28.4 0.2 # 5: 31JAN1990 25.1 -0.2 25.8 -0.2 26.7 0.1 28.4 0.2 # --- # 1365: 24FEB2016 27.1 0.9 28.4 1.8 29.0 2.1 29.5 1.4 # 1366: 02MAR2016 27.3 1.0 28.6 1.8 28.9 1.9 29.5 1.4 # 1367: 09MAR2016 27.7 1.2 28.6 1.6 28.9 1.8 29.6 1.5 # 1368: 16MAR2016 27.5 1.0 28.8 1.7 28.9 1.7 29.6 1.4 # 1369: 23MAR2016 27.2 0.9 28.6 1.4 28.8 1.5 29.5 1.2 

    Tenga en cuenta que fread automáticamente el espacio en blanco fread y final; a veces, esto no es deseable, en cuyo caso establece strip.white = FALSE .


    También podríamos haber empezado con un vector de ancho de columna ww haciendo:

     ww < - c(9, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4) nd <- cumsum(ww) col_ends <- list(beg = c(1, nd[-length(nd)]+1L), end = nd) 

    Y podríamos haber elegido qué columnas excluir de forma más robusta utilizando índices negativos como:

     col_ends < - list(beg = c(1, -10, 15, 19, -23, 28, 32, -36, 41, 45, -49, 54, 58), end = c(9, 14, 18, 22, 27, 31, 35, 40, 44, 48, 53, 57, 61)) 

    Luego reemplace col_ends$beg[ii] con abs(col_ends$beg[ii]) y en la línea siguiente:

     paste0("V", which(col_ends$beg < 0)) 

    Por último, si desea que los nombres de las columnas se lean también programáticamente, puede limpiar con readLines :

     cols < - gsub("\\s", "", sapply(1:(length(col_ends$beg)), function(ii) stri_sub(readLines(URL, n = 4L)[4L], col_ends$beg[ii]+1L, col_ends$end[ii]+1L))) cols <- cols[cols != ""] 

    (tenga en cuenta que combinar este paso con fread requeriría crear una copia de la tabla para eliminar la fila de encabezado y, por lo tanto, sería ineficaz para grandes conjuntos de datos)

    No sé nada sobre R, pero puedo proporcionarle una expresión regular que coincida con tales líneas:

     \s[0-9]{2}[AZ]{3}[0-9]{4}(\s{5}[0-9]+\.[0-9]+[ -][0-9]+\.[0-9]+){4} 

    La forma más directa es usar read.fwf como se indicó anteriormente.

    Bueno, si el objective final es colocarlo en R, siempre podría leerlo en Excel para empezar, usar la función “texto para nublar” para recortar visualmente las columnas y luego guardar el archivo final como CSV. Después de eso, lea el CSV en R.

    Un método fácil para los que no son progtwigdores (que están dispuestos a ir fuera de R)

    1. Abra la página en un navegador web.
    2. Copie y pegue las líneas de datos en un editor de texto. Omita los encabezados de columna.
    3. Utilice Buscar y reemplazar para cambiar varios espacios con un solo espacio (Reemplazar espacio-espacio por espacio. Siga haciendo clic hasta que no queden espacios dobles en la izquierda. Toma solo unos segundos).
    4. Utilice Buscar-y-Reemplazar para reemplazar el guión (-) con un espacio
    5. Para Utilizar Buscar y reemplazar para reemplazar el espacio por coma-espacio.

    Ahora tiene un archivo .csv que también es fácil de leer para un humano; guardarlo Colóquelo en Excel, R o lo que sea, y continúe con el procesamiento.