2014-04-26 13 views
5

Sto provando a creare un loop che legge più file CSV che hanno tutti lo stesso tipo di dati sulla temperatura dell'aria. Tuttavia ci sono righe che voglio saltare sopra i dati. Questi sono "allarmi" nel set di dati. Ogni file può avere una diversa quantità di allarmi, quindi una quantità diversa di righe da saltare. Vedi sotto:Leggi CSV con righe variabili da saltare, bulk

-------------First CSV file--------------- 
Logger 001 
Alarm 1 
Alarm 2 
Alarm 3 
Alarm 4 
Date, Temp 
01/01/2011, -1.2 
01/02/2011, -1.3 
01/03/2011, -1.1 
01/04/2011, -1.2 

-------------Second CSV file--------------- 
Logger 001 
Alarm 1 
Alarm 2 
Alarm 3 
Alarm 4 
Alarm 5 
Alarm 6 
Alarm 7 
Date, Temp 
01/01/2011, -1.2 
01/02/2011, -1.3 
01/03/2011, -1.1 
01/04/2011, -1.2 

Come posso ottenere l'indice di Date, Temp dire read.csv di saltare a quella riga?

for (i in 1:length(csv.list)) { 
    df = read.csv(csv.list[i], header = T, skip=????????) 
} 
+0

Perché non inserire in una tabella temporanea e quindi inserire da lì con il filtro? –

risposta

2

Si potrebbe aggiungere un paio di righe prima del vostro read.table nel vostro ciclo

Usa readLines per leggere nei dati

r <- readLines(textConnection("Logger 001 
       Alarm 1 
       Alarm 2 
       Alarm 3 
       Alarm 4 
       Date, Temp 
       01/01/2011, -1.2 
       01/02/2011, -1.3 
       01/03/2011, -1.1 
       01/04/2011, -1.2")) 

[ma senza la textConnection per IE r <- readLines("yourcsv")]

Trova il numero di riga in cui iniziano le intestazioni effettive, utilizzando grep

dt <- grep("Date",r) 

Leggi nel data - saltare le linee prima di intestazioni

read.table(text=r , header=TRUE, sep="," , skip = dt-1) 


Quindi, per leggere nei file csv multipli - questi saranno memorizzati in un elenco di dati, cornici

df.lst <- lapply(csv.list , function(i) { 
         r <- readLines(i) 
         dt <- grep("Date",r) 
         read.table(text=r , header=TRUE, sep="," , skip = dt-1) 
         }) 
1

count.fields in grado di identificare la prima riga di ogni file che ha due campi separati da virgola. È quindi possibile utilizzarlo per specificare skip. Per esempio:

writeLines('Logger 001 
Alarm 1 
Alarm 2 
Alarm 3 
Alarm 4 
Date, Temp 
01/01/2011, -1.2 
01/02/2011, -1.3 
01/03/2011, -1.1 
01/04/2011, -1.2', f <- tempfile()) 

writeLines('Logger 001 
Alarm 1 
Alarm 2 
Alarm 3 
Alarm 4 
Alarm 5 
Alarm 6 
Alarm 7 
Date, Temp 
01/01/2011, -1.2 
01/02/2011, -1.3 
01/03/2011, -1.1 
01/04/2011, -1.2', f2 <- tempfile()) 

for (x in c(f, f2)) { 
    ind <- match(2, count.fields(x, ',')) 
    df <- read.csv(x, header = T, skip=ind - 1) 
    print(df) 
} 

#   Date Temp 
# 1 01/01/2011 -1.2 
# 2 01/02/2011 -1.3 
# 3 01/03/2011 -1.1 
# 4 01/04/2011 -1.2 
# Date Temp 
# 1 01/01/2011 -1.2 
# 2 01/02/2011 -1.3 
# 3 01/03/2011 -1.1 
# 4 01/04/2011 -1.2 
2

fread dal pacchetto "data.table" potrebbe essere utile per voi dal momento che è abbastanza bravo a "spazzatura" righe di intestazione rilevamento automatico. Ecco un esempio:

In primo luogo, creare due file CSV di esempio

cat("Logger 001 
Alarm 1 
Alarm 2 
Alarm 3 
Alarm 4 
Date, Temp 
01/01/2011, -1.2 
01/02/2011, -1.3 
01/03/2011, -1.1 
01/04/2011, -1.2 
", file = "socsv1.csv", sep = "\n") 

cat("Logger 001 
Alarm 1 
Alarm 2 
Alarm 3 
Alarm 4 
Alarm 5 
Alarm 6 
Alarm 7 
Date, Temp 
01/01/2011, -1.2 
01/02/2011, -1.3 
01/03/2011, -1.1 
01/04/2011, -1.2", file = "socsv2.csv", sep = "\n") 

## Check that they were created 
list.files(pattern = "socsv") 
# [1] "socsv1.csv" "socsv2.csv" 

Ora, basta usare fread e specificare il sep invece di lasciare fread indovinare.

library(data.table) 
lapply(list.files(pattern = "socsv"), fread, sep = ",") 
# [[1]] 
#   Date Temp 
# 1: 01/01/2011 -1.2 
# 2: 01/02/2011 -1.3 
# 3: 01/03/2011 -1.1 
# 4: 01/04/2011 -1.2 
# 
# [[2]] 
#   Date Temp 
# 1: 01/01/2011 -1.2 
# 2: 01/02/2011 -1.3 
# 3: 01/03/2011 -1.1 
# 4: 01/04/2011 -1.2 
0

penso che ci sia un approccio molto più semplice, che sta leggendo i file così come sono, con poche opzioni.

df = read.csv('weather-logger2.csv', colClasses = c('character', 'numeric'), 
       col.names = c('Date', 'Temp'), 
       na.strings = 'Temp', fill = TRUE, stringsAsFactors = FALSE) 

Le prime righe contengono le stringhe che non sono date, che darà NA quando li si converte alle date (dovrete convertire questo modo in ogni caso per l'ulteriore elaborazione), e poi basta solo in subset liberandosi dei valori mancanti:

 Date Temp 
1  Alarm 1 NA 
2  Alarm 2 NA 
3  Alarm 3 NA 
4  Alarm 4 NA 
5  Alarm 5 NA 
6  Alarm 6 NA 
7  Alarm 7 NA 
8  Date NA 
9 01/01/2011 -1.2 
10 01/02/2011 -1.3 
11 01/03/2011 -1.1 
12 01/04/2011 -1.2 

df$Date = as.Date(df$Date, '%d/%m/%Y') 
df = subset(df, !is.na(Date)) 

per ottenere:

  Date Temp 
9 2011-01-01 -1.2 
10 2011-02-01 -1.3 
11 2011-03-01 -1.1 
12 2011-04-01 -1.2