Leggi il file di testo a larghezza fissa

Sto cercando di caricare questo brutto set di dati formattato nella mia sessione 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 

Finora, posso leggere le righe con

  x = readLines(path) 

Ma il file mescola lo ‘spazio bianco’ con ‘-‘ come separatori, e io non sono un esperto di espressioni regolari. Apprezzo qualsiasi aiuto nel trasformare questo in un frame di dati R bello e pulito. Grazie!

Questo è un file a larghezza fissa. Usa read.fwf() per leggerlo:

 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 

Aggiornare

Il pacchetto readr (pubblicato ad aprile 2015) fornisce un'alternativa semplice e veloce.

 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))) 

Confronto di velocità: readr::read_fwf() era ~ 2x più veloce di utils::read.fwf () .

Un altro modo per determinare le larghezze …

 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 ) 

L'argomento -1 nell'ampiezza dice che c'è una colonna di un carattere che dovrebbe essere ignorata, il -5 nell'argomento widths dice che c'è una colonna di cinque caratteri che dovrebbe essere ignorata, allo stesso modo ...

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

Prima di tutto, quella domanda è direttamente da un corso di Coursera “Get Data and Clean It” di Leeks. Mentre c’è un’altra parte della domanda, la parte difficile è la lettura del file.

Detto questo, il corso è principalmente destinato all’apprendimento.

Odio la procedura di larghezza fissa di R. È lento e per un numero elevato di variabili, diventa molto presto un problema per negare determinate colonne, ecc.

Penso che sia più facile usare readLines() e quindi da usare substr() per creare le tue variabili

 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 ) 

Ora puoi usare la funzione read_fwf() nel pacchetto readr Hadley Wickham.

Ci si deve aspettare un enorme miglioramento delle prestazioni, rispetto alla base read.fwf() .

Documento qui l’elenco delle alternative per leggere i file a larghezza fissa in R, oltre a fornire alcuni benchmark per i quali è più veloce.

Il mio approccio preferito è quello di combinare fread con stringi ; è competitivo come l’approccio più veloce e ha il vantaggio aggiuntivo (IMO) di memorizzare i dati come data.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 

Nota che il fread automaticamente gli spazi bianchi strip.white = FALSE e finali - a volte, ciò non è auspicabile, nel qual caso imposta strip.white = FALSE .


Avremmo anche potuto iniziare con un vettore di larghezze di colonne ww eseguendo:

 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) 

E avremmo potuto scegliere quali colonne escludere in modo più efficace utilizzando indici negativi come:

 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)) 

Quindi sostituire col_ends$beg[ii] con abs(col_ends$beg[ii]) e nella riga successiva:

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

Infine, se vuoi che i nomi delle colonne vengano letti anche in modo programmatico, puoi pulire 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 != ""] 

(nota che combinare questo passo con fread richiede la creazione di una copia della tabella per rimuovere la riga di intestazione e quindi risulterebbe inefficiente per i grandi insiemi di dati)

Non so nulla di R, ma posso darti una regex che corrisponderà a tali linee:

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

Il modo più diretto è usare read.fwf come indicato sopra.

Bene, se l’objective finale è quello di inserirlo in R, puoi sempre leggerlo in Excel per iniziare, utilizzare la funzione “text to cloumns” per ritagliare visivamente le colonne, quindi salvare il file finale come CSV. Quindi leggi il CSV in R.

Un metodo semplice se per i non programmatori (che sono disposti ad andare al di fuori di R)

  1. Apri la pagina in un browser web.
  2. Copia e incolla le righe di dati in un editor di testo. Ometti le intestazioni delle colonne.
  3. Usa la funzione di ricerca e sostituzione per modificare più spazi con un singolo spazio (sostituisci spazio-spazio per spazio. Continua a fare clic finché non rimangono due spazi vuoti. Prende solo secondi).
  4. Usa search-and-replace per sostituire dash (-) con uno spazio
  5. Per utilizzare Cerca e sostituisci per sostituire lo spazio con virgola-spazio.

Ora hai un file .csv che è anche facile da leggere per un essere umano; salvarla. Caricalo in Excel, R o altro e continua con l’elaborazione.