Qual è un metodo efficiente per la separazione e aggregazione intervalli di righe timestamp in un frame di dati?

StackOverflow https://stackoverflow.com/questions/2441136

  •  19-09-2019
  •  | 
  •  

Domanda

Da un frame di dati con file timestamp (risultati strptime), qual è il metodo migliore per aggregare le statistiche per gli intervalli?

Gli intervalli potrebbero essere un'ora, un giorno, ecc

C'è la funzione aggregate, ma che non aiuta ad assegnare ogni riga per un intervallo. Sto pensando di aggiungere una colonna per il frame di dati che denota l'intervallo e l'uso che, con aggregate, ma se c'è una soluzione migliore sarebbe bello sentirlo.

Grazie per tutti i puntatori!


Esempio Dati

Cinque file con timestamp suddivise in intervalli di 15 minuti da 3:00.

Intervallo 1

  • "2010-01-13 03:02:38 UTC"
  • "2010-01-13 03:08:14 UTC"
  • "2010-01-13 03:14:52 UTC"

Intervallo 2

  • "2010-01-13 03:20:42 UTC"
  • "2010-01-13 03:22:19 UTC"

Conclusione

Usando un pacchetto serie temporale come xts dovrebbe essere la soluzione; tuttavia ho avuto successo con loro e senza fiato utilizzando cut. Come ho attualmente solo bisogno di tracciare istogrammi, con le file raggruppati per intervallo di tempo, questo era sufficiente.

cut viene utilizzato è piaciuto così:

interv <- function(x, start, period, num.intervals) {
  return(cut(x, as.POSIXlt(start)+0:num.intervals*period))
}
È stato utile?

Soluzione

Le funzioni standard per dividere i vettori sono cut e findInterval:

v <- as.POSIXct(c(
  "2010-01-13 03:02:38 UTC",
  "2010-01-13 03:08:14 UTC",
  "2010-01-13 03:14:52 UTC",
  "2010-01-13 03:20:42 UTC",
  "2010-01-13 03:22:19 UTC"
))

# Your function return list:
interv(v, as.POSIXlt("2010-01-13 03:00:00 UTC"), 900)
# [[1]]
# [1] "2010-01-13 03:00:00"
# [[2]]
# [1] "2010-01-13 03:00:00"
# [[3]]
# [1] "2010-01-13 03:00:00"
# [[4]]
# [1] "2010-01-13 03:15:00 CET"
# [[5]]
# [1] "2010-01-13 03:15:00 CET"

# cut returns factor, you must provide proper breaks:
cut(v, as.POSIXlt("2010-01-13 03:00:00 UTC")+0:2*900)
# [1] 2010-01-13 03:00:00 2010-01-13 03:00:00 2010-01-13 03:00:00
# [4] 2010-01-13 03:15:00 2010-01-13 03:15:00
# Levels: 2010-01-13 03:00:00 2010-01-13 03:15:00

# findInterval returns vector of interval id (breaks like in cut)
findInterval(v, as.POSIXlt("2010-01-13 03:00:00 UTC")+0:2*900)
# [1] 1 1 1 2 2

Per la cronaca: cut ha un metodo per il tipo POSIXt, ma purtroppo non c'è modo per fornire argomento start, effetto è:

cut(v,"15 min")
# [1] 2010-01-13 03:02:00 2010-01-13 03:02:00 2010-01-13 03:02:00
# [4] 2010-01-13 03:17:00 2010-01-13 03:17:00
# Levels: 2010-01-13 03:02:00 2010-01-13 03:17:00

Come si vede che iniziamo a 03:02:00. Si potrebbe pasticciare con le etichette di fattore di uscita (convertire le etichette in tanto, rotondo in qualche modo e riconvertire a carattere).

Altri suggerimenti

serie storiche pacchetto. Il pacchetto XTS ha funzioni progettato specificamente per farlo. O guardare le funzioni di aggregazione e rollapply nel pacchetto zoo.

L'ebook rmetrics ha una discussione utile, tra cui un confronto delle prestazioni dei vari pacchetti: https://www.rmetrics.org/files/freepdf/TimeSeriesFAQ.pdf

Modifica : Guarda la mia risposta a questa domanda . Fondamentalmente è necessario troncare ogni timestamp in un intervallo specifico e poi fare l'aggregazione utilizzando quelle nuove timestamp tronche come vettore di raggruppamento.

Questa è una domanda interessante; con la proliferazione dei vari pacchetti e metodi serie temporali, ci deve essere un approccio per la discretizzazione serie temporali irregolari diversa dalla forza bruta che il PO suggerisce. Ecco un modo "di alto livello" per ottenere gli intervalli che è possibile utilizzare per aggregate et al, utilizzando una versione di cut definito per gli oggetti chron.

require(chron)
require(timeSeries)

my.times <- "
2010-01-13 03:02:38 UTC
2010-01-13 03:08:14 UTC
2010-01-13 03:14:52 UTC
2010-01-13 03:20:42 UTC
2010-01-13 03:22:19 UTC
"

time.df <- read.delim(textConnection(my.times),header=FALSE,sep="\n",strip.white=FALSE)
time.seq <- seq(trunc(timeDate(time.df[1,1]),units="hours"),by=15*60,length=nrow(time.df))
intervals <- as.numeric(cut(as.chron(as.character(time.df$V1)),breaks=as.chron(as.character(time.seq))))

È possibile ottenere

intervals  
[1] 1 1 1 2 2

, che è ora possibile aggiungere alla cornice di dati e di aggregazione.

Le acrobazie coercizione di cui sopra (da personaggio a TimeDate a carattere di Chron) è un po 'un peccato, quindi se ci sono soluzioni più pulite per la categorizzazione dei dati in tempo irregolari utilizzando XTS o uno qualsiasi degli altri pacchetti TimeSeries, mi piacerebbe sentir parlare loro pure! ..

Sono anche curioso di sapere che cosa sarebbe l'approccio più efficiente per binning larga ad alta frequenza serie temporali irregolari, per esempio creazione di barre di 1 minuto di volume sui dati tick per un titolo molto liquido.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top