2016-05-10 2 views
1

Y at-il une fonction de n'importe quel package qui calcule combien de fois un ID d'une ligne apparaît sur les x dernières heures. Je vais appeler cela "vitesse".Manière efficace dans R de compter les lignes par ID sur une fenêtre temporelle glissante?

La colonne cible que je veux calculer est représentée par 'VEL_7H'. En d'autres termes, combien de fois l'ID est apparue sur les 7 dernières heures?

ID  TIME     VEL_7H 
1144727 2016-04-01 09:56:12 0 
1144727 2016-04-01 15:16:03 1 
1144727 2016-04-01 15:26:14 2 
1144727 2016-04-02 09:48:48 0 
1799567 2016-04-14 14:41:06 0 
1799567 2016-04-14 17:51:06 1 
2067650 2016-04-17 12:34:52 0 

Existe-t-il une fonction utilisant des vecteurs d'heure et d'ID, et une plage spécifiée, qui donne la colonne VEL_7H?

+0

Pourriez-vous fournir un 'dput (votre_exemple)', il est donc plus facile de copier-coller dans R? – Frank

Répondre

1

Pour optimiser les performances, je pense que Rcpp est approprié:

library(Rcpp); 
df <- data.frame(ID=c(1144727L,1144727L,1144727L,1144727L,1799567L,1799567L,2067650L),TIME=as.POSIXct(c('2016-04-01 09:56:12','2016-04-01 15:16:03','2016-04-01 15:26:14','2016-04-02 09:48:48','2016-04-14 14:41:06','2016-04-14 17:51:06','2016-04-17 12:34:52'))); 
cppFunction(' 
    IntegerVector countTrailingIDs(IntegerVector ids, DoubleVector times, double window) { 
     IntegerVector res(ids.size()); 
     for (int i = 0; i < ids.size(); ++i) { 
      int id = ids[i]; 
      double trailTime = times[i]-window; 
      for (int j = i-1; j >= 0 && ids[j] == id && times[j] >= trailTime; --j) 
       ++res[i]; 
     } 
     return res; 
    } 
'); 
df$VEL_7H <- countTrailingIDs(df$ID,df$TIME,60*60*7); 
df; 
##  ID    TIME VEL_7H 
## 1 1144727 2016-04-01 09:56:12  0 
## 2 1144727 2016-04-01 15:16:03  1 
## 3 1144727 2016-04-01 15:26:14  2 
## 4 1144727 2016-04-02 09:48:48  0 
## 5 1799567 2016-04-14 14:41:06  0 
## 6 1799567 2016-04-14 17:51:06  1 
## 7 2067650 2016-04-17 12:34:52  0 

Notez que la fonction exige ids et times à commander selon l'identifiant et le temps.

+0

Wow. Assez rapide et simple (vélocité 1.6M calculée instantanément). Merci pour la solution, je vais accepter la réponse. – jbrettas

3

Nous pouvons utiliser une approche split-apply-combiner classique dans la base R d'abord diviser la trame de données par ID, additionnez le nombre d'entrées dans les 7 dernières heures, puis créez une nouvelle colonne avec les valeurs suivantes:

sdf <- split(df, df$ID) 
last7 <- function(df) sapply(1:nrow(df), function(i) sum(df[i, "TIME"] - df[1:i, "TIME"] <= 60*60*7) - 1L) 
df$VEL_7H <- unlist(sapply(sdf, last7)) 
df 
#  ID    TIME VEL_7H 
# 1 1144727 2016-04-01 09:56:12  0 
# 2 1144727 2016-04-01 15:16:03  1 
# 3 1144727 2016-04-01 15:26:14  2 
# 4 1144727 2016-04-02 09:48:48  0 
# 5 1799567 2016-04-14 14:41:06  0 
# 6 1799567 2016-04-14 17:51:06  1 
# 7 2067650 2016-04-17 12:34:52  0 
+0

Merci. Est-ce bon de voir ces fonctions de base R fournissant des solutions simples. Je pense toujours que c'est étrange qu'il n'y ait aucune fonction de quelque paquet faisant quelque chose comme ceci. Upvoted (: – jbrettas