Le problème que j'essaye de résoudre est que j'ai une trame de données avec une variable POSIXct triée dedans. Chaque ligne est catégorisée et je veux obtenir les différences de temps entre chaque ligne pour chaque niveau et ajouter ces données dans une nouvelle variable. Le problème reproductible est le suivant. La fonction ci-dessous est juste pour créer des échantillons de données avec des temps aléatoires aux fins de cette question.
random.time <- function(N, start, end) {
st <- as.POSIXct(start)
en <- as.POSIXct(end)
dt <- as.numeric(difftime(en, st, unit="sec"))
ev <- sort(runif(N, 0, dt))
rt <- st + ev
return(rt)
}
Le code pour simuler le problème est le suivant:
set.seed(123)
category <- sample(LETTERS[1:5], 20, replace=TRUE)
randtime <- random.time(20, '2015/06/01 08:00:00', '2015/06/01 18:00:00')
df <- data.frame(category, randtime)
La trame de données résultante attendue est la suivante:
>category randtime timediff (secs)
>A 2015-06-01 09:05:00 0
>A 2015-06-01 09:06:30 90
>A 2015-06-01 09:10:00 210
>B 2015-06-01 10:18:58 0
>B 2015-06-01 10:19:58 60
>C 2015-06-01 08:14:00 0
>C 2015-06-01 08:16:30 150
Chaque sous-groupe dans la sortie aura la première ligne avec la valeur timediff de 0 car il n'y a pas de ligne précédente. J'ai pu regrouper par catégorie et appeler la fonction suivante pour calculer les différences, mais je n'ai pas pu obtenir la sortie finale pour tous les groupes de catégories.
getTimeDiff <- function(x) {
no_rows <- nrow(x)
if(no_rows > 1) {
for(i in 2:no_rows) {
t <- x[i, "randtime"] - x[i-1, "randtime"]
}
}
}
J'y suis depuis deux jours sans chance, donc j'apprécierais grandement toute aide. Merci.
Essaye ça:
library(dplyr)
df %>%
arrange(category, randtime) %>%
group_by(category) %>%
mutate(diff = randtime - lag(randtime),
diff_secs = as.numeric(diff, units = 'secs'))
# category randtime diff diff_secs
# (fctr) (time) (dfft) (dbl)
# 1 A 2015-06-01 11:10:54 NA hours NA
# 2 A 2015-06-01 15:35:04 4.402785 hours 15850.027
# 3 A 2015-06-01 17:01:22 1.438395 hours 5178.222
# 4 B 2015-06-01 08:14:46 NA hours NA
# 5 B 2015-06-01 16:53:43 518.955379 hours 1868239.364
# 6 B 2015-06-01 17:37:48 44.090950 hours 158727.420
Vous pouvez également ajouter replace(is.na(.), 0)
à la chaîne.
Dans la base R, vous pouvez utiliser:
# creating an ordered data.frame
df <- data.frame(category, randtime)
df <- df[order(df$category, df$randtime),]
# calculating the timedifference
# option 1:
df$tdiff <- unlist(tapply(df$randtime, INDEX = df$category,
FUN = function(x) c(0, `units<-`(diff(x), "secs"))))
# option 2:
df$tdiff <- unlist(tapply(df$randtime, INDEX = df$category,
FUN = function(x) c(0, diff(as.numeric(x)))))
qui donne:
> df category randtime tdiff 6 A 2015-06-01 11:10:54 0.0000 15 A 2015-06-01 15:35:04 15850.0271 18 A 2015-06-01 17:01:22 5178.2223 1 B 2015-06-01 08:14:46 0.0000 17 B 2015-06-01 16:53:43 31137.3227 19 B 2015-06-01 17:37:48 2645.4570 3 C 2015-06-01 10:09:50 0.0000 7 C 2015-06-01 12:46:40 9409.9693 9 C 2015-06-01 13:56:29 4188.4578 10 C 2015-06-01 14:24:18 1669.1326 12 C 2015-06-01 14:54:25 1807.1447 14 C 2015-06-01 15:05:07 641.7068 2 D 2015-06-01 09:28:16 0.0000 13 D 2015-06-01 14:55:40 19644.8313 4 E 2015-06-01 10:18:58 0.0000 5 E 2015-06-01 10:53:29 2071.2223 8 E 2015-06-01 13:26:26 9176.6263 11 E 2015-06-01 14:33:25 4019.0319 16 E 2015-06-01 15:57:16 5031.4183 20 E 2015-06-01 17:56:33 7156.8849
Si vous voulez des minutes ou des heures, vous pouvez utiliser "mins"
ou "hours"
au lieu de "secs"
.
Une alternative avec le data.table
paquet:
library(data.table)
# creating an ordered/keyed data.table
dt <- data.table(category, randtime, key = c("category", "randtime"))
# calculating the timedifference
# option 1:
dt[, tdiff := difftime(randtime, shift(randtime, fill=randtime[1L]), units="secs"), by=category]
# option 2:
dt[, tdiff := c(0, `units<-`(diff(randtime), "secs")), by = category]
# option 3:
dt[ , test := c(0, diff(as.numeric(randtime))), category]
ce qui se traduit par:
> dt category randtime tdiff 1: A 2015-06-01 11:10:54 0.0000 secs 2: A 2015-06-01 15:35:04 15850.0271 secs 3: A 2015-06-01 17:01:22 5178.2223 secs 4: B 2015-06-01 08:14:46 0.0000 secs 5: B 2015-06-01 16:53:43 31137.3227 secs 6: B 2015-06-01 17:37:48 2645.4570 secs 7: C 2015-06-01 10:09:50 0.0000 secs 8: C 2015-06-01 12:46:40 9409.9693 secs 9: C 2015-06-01 13:56:29 4188.4578 secs 10: C 2015-06-01 14:24:18 1669.1326 secs 11: C 2015-06-01 14:54:25 1807.1447 secs 12: C 2015-06-01 15:05:07 641.7068 secs 13: D 2015-06-01 09:28:16 0.0000 secs 14: D 2015-06-01 14:55:40 19644.8313 secs 15: E 2015-06-01 10:18:58 0.0000 secs 16: E 2015-06-01 10:53:29 2071.2223 secs 17: E 2015-06-01 13:26:26 9176.6263 secs 18: E 2015-06-01 14:33:25 4019.0319 secs 19: E 2015-06-01 15:57:16 5031.4183 secs 20: E 2015-06-01 17:56:33 7156.8849 secs