2017-10-21 5 views
-1

j'ai une trame de données de ce type (le vrai est beaucoup plus grand):Mark chaque ligne d'une grande trame de données par l'intermédiaire de deux variables

time<-c(as.POSIXct('2011-11-11 06:00:00'),as.POSIXct('2011-11-11 06:05:00'),as.POSIXct('2011-11-11 07:05:00'), 
      as.POSIXct('2011-11-11 07:10:00'),as.POSIXct('2011-11-11 07:13:00'),as.POSIXct('2011-11-11 07:33:00'), 
      as.POSIXct('2011-11-11 05:05:00'),as.POSIXct('2011-11-11 06:05:00'),as.POSIXct('2011-11-11 06:20:00'), 
      as.POSIXct('2011-11-11 09:05:00')) 
plate<-c('a','a','a','b','c','d','e','e','e','e') 
df<-data.frame(time,plate) 

La variable time représente le temps que le véhicule identifié par le dispositif vidéo . La variable plate représente la plaque du véhicule. La trame de données a été bien ordonnée par plate d'une part et time d'autre part. Compte tenu de cela, je veux diviser le voyage de chaque véhicule en marquant les rangées. Différents véhicules (plates) représentent certainement différents trajets. Pour un véhicule, la différence de temps identifiée au cours d'un voyage doit être inférieure à 30 minutes, sinon les lignes doivent appartenir à des trajets différents.

Dans mon chemin, je ferai cela par le code suivant:

trip<-vector() 
trip[1]<-1 
time_diff<-as.POSIXct('2011-11-11 07:00:00')-as.POSIXct('2011-11-11 06:30:00') 
for (x in 2:nrow(df)) { 
    if (!df$plate[x]==df$plate[x-1]) (trip[x]<-trip[x-1]+1 
) else{if (df$time[x]-df$time[x-1]<time_diff) (trip[x]<-trip[x-1] 
) else (trip[x]<-trip[x-1]+1)} 
} 
df<-cbind(df,trip) 

Cependant, mon df contient plus de sept millions de lignes ainsi ma méthode sera très lente. Je demande donc s'il existe des moyens plus efficaces de le faire.

Répondre

2

Je suggère d'utiliser dplyr pour cela, mais avec 7M lignes, vous pourriez envisager data.table solution si cela ne fonctionne pas bien pour vous.

library(dplyr) 

time_diff<-as.POSIXct('2011-11-11 07:00:00')-as.POSIXct('2011-11-11 06:30:00') 

df %>% 
    arrange(time) %>% # it's important, so I reinforce it here 
    group_by(plate) %>% 
    mutate(
    trip = cumsum(c(TRUE, diff(time) > time_diff)) 
) %>% 
    ungroup() 
# # A tibble: 10 × 3 
#     time plate trip 
#     <dttm> <fctr> <int> 
# 1 2011-11-11 06:00:00  a  1 
# 2 2011-11-11 06:05:00  a  1 
# 3 2011-11-11 07:05:00  a  2 
# 4 2011-11-11 07:10:00  b  1 
# 5 2011-11-11 07:13:00  c  1 
# 6 2011-11-11 07:33:00  d  1 
# 7 2011-11-11 05:05:00  e  1 
# 8 2011-11-11 06:05:00  e  2 
# 9 2011-11-11 06:20:00  e  2 
# 10 2011-11-11 09:05:00  e  3 

Je préfère de beaucoup la solution ci-dessus à l'aide group_by, mais si vous voulez que le trip d'être unique à travers les plaques, une technique consiste à gérer vous-même le regroupement (nécessitant commande stricte):

df %>% 
    arrange(plate, time) %>% 
    mutate(
    trip = cumsum(plate != lag(plate, default = plate[1]) | c(TRUE, diff(time) > time_diff)) 
) 
#     time plate trip 
# 1 2011-11-11 06:00:00  a 1 
# 2 2011-11-11 06:05:00  a 1 
# 3 2011-11-11 07:05:00  a 2 
# 4 2011-11-11 07:10:00  b 3 
# 5 2011-11-11 07:13:00  c 4 
# 6 2011-11-11 07:33:00  d 5 
# 7 2011-11-11 05:05:00  e 6 
# 8 2011-11-11 06:05:00  e 7 
# 9 2011-11-11 06:20:00  e 7 
# 10 2011-11-11 09:05:00  e 8