J'ai un data.table de données de timestamp qui comprend à la fois l'heure de début et l'heure de fin pour les personnes, arrondies aux intervalles de 15 minutes les plus proches. Je veux pouvoir dupliquer chaque ligne pour avoir le même nombre de copies que le nombre d'intervalles de 15 minutes couverts par leurs données d'entrée/sortie, tout en ajoutant une nouvelle colonne qui répertorie l'intervalle de 15 minutes (par exemple, une personne pointant à 10h00 et partant à 11h00, il y aurait quatre lignes créées, une avec l'heure indiquée à 10h00, une à 10h15, une à 10h30 et une à 10h45).
Réponses
Trop de publicités?Je n'ai aucune idée de ce à quoi ressemble vos données, mais voici ce que j'ai compris.
library(padr)
library(zoo)
#données
utilisateur<-"4"
heures<-c("10:00","11:15")
heures<-as.POSIXct(heures,format="%H:%M")
#créer un data frame
dt<-data.frame(utilisateur,heures)
> dt
utilisateur heures
1 4 2018-05-31 10:00:00
2 4 2018-05-31 11:15:00
#ajuster les intervalles
dt<-pad(dt, interval="15 min")
#propager l'identifiant utilisateur
dt<-na.locf(dt)
>dt
utilisateur heures
1 4 2018-05-31 10:00:00
2 4 2018-05-31 10:15:00
3 4 2018-05-31 10:30:00
4 4 2018-05-31 10:45:00
5 4 2018-05-31 11:00:00
6 4 2018-05-31 11:15:00
C'est en fait juste une application très simple de la transposition et de la dernière observation reportée.
Voici mon employé:
emp <- data.frame(empid = 001, timein = as.POSIXct('2018-05-31 8:00'), timeout = as.POSIXct('2018-05-31 17:00'))
Voici mon wrapper de dernière observation reportée (mais il y a aussi zoo::na.locf
)
locf <- function(y) c(NA, na.omit(y))[cumsum(!is.na(y))+1]
Maintenant transposer:
emplong <- reshape(emp, direction='long', idvar='empid', varying=list(2:3),
times=c('in', 'out'), timevar='status')
Cela donne:
empid status timein
1.in 1 in 2018-05-31 08:00:00
1.out 1 out 2018-05-31 17:00:00
Créez maintenant un planning:
roster <- data.frame('times' = seq(
from=as.POSIXct('2018-05-31 00:00:00'),
to=as.POSIXct('2018-06-01 00:00:00'),
by=15*60))
Et fusionnez:
roster <- merge(roster, emplong[, -1], by.x='times', by.x='timein', all=T)
Et LOCF
roster$status <- locf(roster$status )
roster$status[is.na(roster$status )] <- 'out'
Cela donne:
> roster
times status
1 2018-05-31 00:00:00 out
2 2018-05-31 00:15:00 out
3 2018-05-31 00:30:00 out
4 2018-05-31 00:45:00 out
5 2018-05-31 01:00:00 out
...
31 2018-05-31 07:30:00 out
32 2018-05-31 07:45:00 out
33 2018-05-31 08:00:00 in
34 2018-05-31 08:15:00 in
...
67 2018-05-31 16:30:00 in
68 2018-05-31 16:45:00 in
69 2018-05-31 17:00:00 out
70 2018-05-31 17:15:00 out
Pour une solution data.table
, en supposant que votre data.table
est formatée comme ceci :
library(data.table)
dt <- data.table(
employee = c("John", "Paul", "Mary"),
clock.in = as.POSIXct(c("10:30", "12:30", "13:15"), format = "%R"),
clock.out = as.POSIXct(c("11:00", "13:15", "14:15"), format = "%R")
)
> dt
employee clock.in clock.out
1: John 2018-05-31 10:30:00 2018-05-31 11:00:00
2: Mary 2018-05-31 13:15:00 2018-05-31 14:15:00
3: Paul 2018-05-31 12:30:00 2018-05-31 13:15:00
Utilisez setkey
pour permettre une jointure entre la table de base et une table où une séquence d'intervalle de 15 minutes est créée entre les heures de pointage de début et de fin :
setkey(dt, employee)
> dt[dt[, seq.POSIXt(clock.in, clock.out, by = 60*15), by = employee]]
employee clock.in clock.out V1
1: John 2018-05-31 10:30:00 2018-05-31 11:00:00 2018-05-31 10:30:00
2: John 2018-05-31 10:30:00 2018-05-31 11:00:00 2018-05-31 10:45:00
3: John 2018-05-31 10:30:00 2018-05-31 11:00:00 2018-05-31 11:00:00
4: Mary 2018-05-31 13:15:00 2018-05-31 14:15:00 2018-05-31 13:15:00
5: Mary 2018-05-31 13:15:00 2018-05-31 14:15:00 2018-05-31 13:30:00
6: Mary 2018-05-31 13:15:00 2018-05-31 14:15:00 2018-05-31 13:45:00
7: Mary 2018-05-31 13:15:00 2018-05-31 14:15:00 2018-05-31 14:00:00
8: Mary 2018-05-31 13:15:00 2018-05-31 14:15:00 2018-05-31 14:15:00
9: Paul 2018-05-31 12:30:00 2018-05-31 13:15:00 2018-05-31 12:30:00
10: Paul 2018-05-31 12:30:00 2018-05-31 13:15:00 2018-05-31 12:45:00
11: Paul 2018-05-31 12:30:00 2018-05-31 13:15:00 2018-05-31 13:00:00
12: Paul 2018-05-31 12:30:00 2018-05-31 13:15:00 2018-05-31 13:15:00