Estoy intentando cargar este conjunto de datos con formato feo en mi sesión de 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 marco de datos R agradable y limpio. ¡Gracias!
r
fixed-width
Fernando
fuente
fuente
read.fwf
a leer datos con formato de ancho fijo.Respuestas:
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
(lanzado en abril de 2015) ofrece una alternativa sencilla 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 veces más rápido queutils::read.fwf ()
.fuente
readr::fwf_empty
que intentará adivinar los anchos por ti. Los ejemplos dereadr::read_fwf
muestran el uso dereadr::fwf_empty
.Otra forma de determinar anchos ...
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 -1 en el argumento de anchos 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 debería ignorarse, de la misma manera ...
ref: https://www.inkling.com/read/r-cookbook-paul-teetor-1st/chapter-4/recipe-4-6
fuente
En primer lugar, esa pregunta proviene directamente de un curso de Coursera "Obtener datos y limpiarlos" 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 al aprendizaje.
Odio el procedimiento de ancho fijo de R. Es lento y para una gran cantidad de variables, rápidamente se convierte en una molestia negar ciertas columnas, etc.
Creo que es más fácil de usar
readLines()
y luego de ese usosubstr()
para hacer sus variablesx <- 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 )
fuente
mydata <- data.frame(var4 = substr(x,29,32))
si solo necesitara la cuarta columna de datos. Además, para los usuarios de Windows, Notepad ++ con el complemento TextFX le proporcionará una regla de caracteres contados simple y simple para que pueda averiguar qué poner en los valores de inicio y finalizaciónsubstr
. Sin embargo, tenga en cuenta que el valor de parada es uno más que la posición del último carácter que desea conservar.Ahora puede usar la
read_fwf()
función en elreadr
paquete de Hadley Wickham .Se espera una gran mejora del rendimiento, en comparación con la base
read.fwf()
.fuente
Documento aquí la lista de alternativas para leer archivos de ancho fijo en R, además de proporcionar algunos puntos de referencia para los que es más rápido.
Mi enfoque preferido es combinar
fread
constringi
; es competitivo como el enfoque más rápido y tiene el beneficio adicional (IMO) de almacenar sus datos comodata.table
: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
elimina automáticamente los espacios en blanco iniciales y finales; a veces, esto no es deseable, en cuyo caso se establecestrip.white = FALSE
.También podríamos haber comenzado con un vector de anchos 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 manera más sólida mediante el uso de í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]
conabs(col_ends$beg[ii])
y en la siguiente línea:paste0("V", which(col_ends$beg < 0))
Por último, si desea que los nombres de las columnas también se lean mediante programación, 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 del encabezado y, por lo tanto, sería ineficiente para conjuntos de datos grandes)fuente
No sé nada sobre R, pero puedo proporcionarle una expresión regular que coincidirá con esas líneas:
\s[0-9]{2}[A-Z]{3}[0-9]{4}(\s{5}[0-9]+\.[0-9]+[ -][0-9]+\.[0-9]+){4}
fuente