Ce qui est une méthode efficace pour le partitionnement et l'agrégation des intervalles de lignes horodatés dans une trame de données?

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

  •  19-09-2019
  •  | 
  •  

Question

A partir d'un cadre de données avec des lignes horodatés (résultats de strptime), quelle est la meilleure méthode pour agréger les statistiques des intervalles?

Intervalles pourrait être une heure, une journée, etc.

Il y a la fonction aggregate, mais cela ne suffit pas assigner chaque ligne à un intervalle. Je prévois d'ajouter une colonne à la trame de données qui indique l'intervalle et l'utilisation qui avec aggregate, mais s'il y a une meilleure solution que ce serait génial d'entendre.

Merci pour tous les pointeurs!


Exemple de données

Cinq lignes avec horodatages divisé en intervalles de 15 minutes à partir de 03h00.

Intervalle 1

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

Intervalle 2

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

Conclusion

L'utilisation d'un ensemble de séries chronologiques telles que xts devrait être la solution; mais je n'ai pas réussi à les utiliser et poussif en utilisant cut. Comme je l'ai besoin actuellement que pour tracer des histogrammes, avec des lignes groupées par intervalle, cela suffit.

cut est utilisé aimait tant:

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

La solution

Fonctions standard pour des vecteurs divisés sont cut et 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

Pour mémoire: cut a une méthode pour le type de POSIXt, mais malheureusement, il n'y a aucun moyen de fournir argument start, l'effet est:

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

Comme vous le voyez COMMENÇONS à 03:02:00. Vous pouvez jouer avec les étiquettes de facteur de sortie (convertir les étiquettes en temps, en quelque sorte autour et reconvertir le caractère).

Autres conseils

Utilisez un paquet série temporelle. Le paquet XTS a des fonctions conçu spécifiquement pour le faire. Ou regarder les fonctions d'agrégation et rollapply dans le package zoo.

L'ebook rmetrics a une discussion utile, y compris une comparaison des performances des différents forfaits: https://www.rmetrics.org/files/freepdf/TimeSeriesFAQ.pdf

Modifier : Regardez ma réponse à cette question . Fondamentalement, vous devez tronquer chaque horodatage dans un intervalle spécifique puis effectuez l'agrégation en utilisant ces nouveaux horodatages tronqués comme vecteur de groupement.

Ceci est une question intéressante; avec la prolifération des différents paquets de séries chronologiques et les méthodes, il devrait être une approche pour binning séries chronologiques irrégulières autre que par la force brutale que l'OP suggère. Voici une façon de « haut niveau » pour obtenir les intervalles que vous pouvez ensuite utiliser pour aggregate et al, en utilisant une version de cut définie pour les objets 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))))

Vous obtenez

intervals  
[1] 1 1 1 2 2

que vous pouvez ajouter à la trame de données et d'agrégats.

Les acrobaties coersion ci-dessus (de caractère à timedate à caractère chron) est un peu malheureux, donc s'il existe des solutions plus propres pour binning données de temps irréguliers à l'aide XTS ou l'un des autres forfaits TimeSeries, je serais ravi d'entendre parler eux aussi! ..

Je suis aussi curieux de savoir ce qui serait l'approche la plus efficace pour binning grande haute fréquence des séries temporelles irrégulières, par exemple la création barres de volume 1 minute sur des données de graduation pour un stock très liquide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top