Problème avec la fonction within (lubridate)

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Jonathan Costa
Messages : 12
Enregistré le : 27 Nov 2017, 16:15

Problème avec la fonction within (lubridate)

Messagepar Jonathan Costa » 06 Oct 2021, 14:46

Bonjour à tous,

J'ai un soucis avec la fonction %within% de lubridate.

J'ai deux dataframe comme ci après :

Code : Tout sélectionner

df1 <- data.frame(a=c("2021-02-15 01:17","2021-05-30 03:33"),b=c("2021-02-15 01:27","2021-05-30 03:33"),eol=c("E01","E01"),Intervalle_df2=NA)
df2 <- data.frame(Timestamp.start=c("15/02/2021 01:15","15/02/2021 01:22"),Timestamp.end=c("15/02/2021 02:36","15/02/2021 01:32"),Duration=c("01:21","00:10"),eol=c("E01","E01"))



J'aimerai dans un premier temps savoir si l'intervalle [a;b] du df1 est compris dans l'intervalle [Timestamp.start;Timestamp.end] du df2 .

pour l'instant j'ai seulement réussi à faire fonctionner un script avec seulement une date et non pas un intervalle :

Code : Tout sélectionner

for (eol in unique(df1$eol)){
df1$Intervalle_df2 <-  ymd_hm(df1$a[df1$eol==eol]) %within%
  as.list(interval(dmy_hm(df2$Timestamp.start),
                   dmy_hm(df2$Timestamp.end)))
}


Dans un second temps, j'aimerai pouvoir calculer la différence de temps entre l'intervalle [a;b] et l'intervalle [Timestamp.start;Timestamp.end] comme ci-après :

Code : Tout sélectionner

df_final <- data.frame(a=c("2021-02-15 01:17","2021-05-30 03:33"),b=c("2021-02-15 01:27","2021-05-30 03:33"),eol=c("E01","E01"),Intervalle_df2=c("TRUE","FALSE"),Duree_df2=c("8min","0min"))


Je vous remercie grandement pour votre aide.

Cordialement,
Jonathan

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Problème avec la fonction within (lubridate)

Messagepar Mickael Canouil » 06 Oct 2021, 16:01

Bonjour,

je ne comprend pas le problème ...

Code : Tout sélectionner

library("lubridate")
df1$Intervalle_df2 <- interval(ymd_hm(df1$a), ymd_hm(df1$b)) %within% 
  interval
(dmy_hm(df2$Timestamp.start), dmy_hm(df2$Timestamp.end)) 

Il serait plus malin de convertir les colonnes de dates en dates en amont, plutôt que de répéter l'opération sur chaque élément (donc pas comme le code au dessus et le votre).
Au passage, j'ai juste suivi ce qui est écrit dans la documentation https://lubridate.tidyverse.org/referen ... erval.html

EDIT : En vraiment pas optimale et moche, très littéralement que vous semblez vouloir faire :

Code : Tout sélectionner

df1 <- data.frame(a=c("2021-02-15 01:17","2021-05-30 03:33"),b=c("2021-02-15 01:27","2021-05-30 03:33"),eol=c("E01","E01"),Intervalle_df2=NA)
df2 <- data.frame(Timestamp.start=c("15/02/2021 01:15","15/02/2021 01:22"),Timestamp.end=c("15/02/2021 02:36","15/02/2021 01:32"),Duration=c("01:21","00:10"),eol=c("E01","E01"))

library(lubridate)
#> 
#> Attachement du package : 'lubridate'
#> Les objets suivants sont masqués depuis 'package:base':
#> 
#>     date, intersect, setdiff, union

int_df2 <- interval(dmy_hm(df2$Timestamp.start), dmy_hm(df2$Timestamp.end))
diff_df2 <- format(dmy_hm(df2$Timestamp.end) - dmy_hm(df2$Timestamp.start), units = "mins")
int_df1_in_df2 <- interval(ymd_hm(df1$a), ymd_hm(df1$b)) %within% int_df2
# or with remotes:: install_github("tidyverse/lubridate")
int_df1_in_df2 <- interval(ymd_hm(df1$a), ymd_hm(df1$b)) %within% as.list(int_df2)

df1$Intervalle_df2[int_df1_in_df2] <- diff_df2[int_df1_in_df2]
df1
#>                  a                b eol Intervalle_df2
#> 1 2021-02-15 01:17 2021-02-15 01:27 E01        81 mins
#> 2 2021-05-30 03:33 2021-05-30 03:33 E01           <NA>     


A noter, ce qui semble être un oubli dans la définition de la méthode %within% lorsque l'élément de gauche est un interval et à droite une liste d'intervalle.
=> Ouvrir une "issue" sur Github https://github.com/tidyverse/lubridate/issues/1001

Code : Tout sélectionner

int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int2 <- interval(ymd("2001-06-01"), ymd("2002-01-01"))
int2 %within% list(int)
#> Error in int2 %within% list(int) : 
#>   No %within% method with signature a = Interval,  b = list   

=> corrigé dans la version développement sur GitHub.

Cordiaement,
Mickaël
mickael.canouil.fr | rlille.fr

Jonathan Costa
Messages : 12
Enregistré le : 27 Nov 2017, 16:15

Re: Problème avec la fonction within (lubridate)

Messagepar Jonathan Costa » 13 Oct 2021, 12:38

Bonjour Mickael et merci pour ta réponse. Je me suis sûrement mal exprimé désolé je vais essayer de reformuler avec un nouvel exemple.

J'ai à ma disposition deux dataframe :

Code : Tout sélectionner

x = data.table(start=dmy_hm(c("01/06/2021 00:00")), end=dmy_hm(c("01/06/2021 00:10")),eol="E01")
y_stop=data.table(start_stop=dmy_hm(c("01/06/2021 22:10","01/06/2021 00:05")), end_stop=dmy_hm(c("01/06/2021 22:33","01/06/2021 00:07")),eol=c("E01","E01"))


J'ai donc des intervalles de temps dans x et dans y_stop. J'aimerai savoir pour chaque ligne dans x, s'il y a un arrêt correspondant dans y_stop et si oui, de quelle durée ?
En l'occurrence pour la première ligne de x j'ai un arrêt dans y_stop (2ème ligne) correspondant à 2 min.
Mon tableau final ressemblerait à cela :

Code : Tout sélectionner

x_final=data.table(start=dmy_hm(c("01/06/2021 00:00")), end=dmy_hm(c("01/06/2021 00:10")),eol="E01",duration_y_stop=hm("00:02"))


Les intervalles pouvant se chevaucher, la fonction %within% n'est sûrement pas approprié...

Bien à toi,
Jonathan

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Problème avec la fonction within (lubridate)

Messagepar Mickael Canouil » 13 Oct 2021, 15:55

Votre énoncé n'est pas claire de par l'approximation des termes employés, comme "arrêt", le mélange de date et interval dans vos messages.
Et votre exemple illustre exactement l'inverse de ce que vous écrivez, à savoir qu'un interval plus grand (x) doit se trouver dans un interval plus petit (y_stop) ...
Par contre, un interval de "y_stop" peut tout à fait se trouver dans un interval de "x" comme dans votre exemple et dans ce cas le code que j'ai donné précédemment fait exactement ça.
La preuve en code :

Code : Tout sélectionner

library(data.table)
library(lubridate)
<- data.table(start=dmy_hm(c("01/06/2021 00:00")), end=dmy_hm(c("01/06/2021 00:10")),eol="E01")
y_stop <- data.table(start_stop=dmy_hm(c("01/06/2021 22:10","01/06/2021 00:05")), end_stop=dmy_hm(c("01/06/2021 22:33","01/06/2021 00:07")),eol=c("E01","E01"))

x_final <- data.table(start=dmy_hm(c("01/06/2021 00:00")), end=dmy_hm(c("01/06/2021 00:10")),eol="E01",duration_y_stop=hm("00:02"))

int_y_stop <- interval(y_stop$start_stop, y_stop$end_stop)
diff_y_stop <- format(y_stop$end_stop - y_stop$start_stop, units = "mins")
x$duration_y_stop <- sapply(interval(x$start, x$end), function(x) diff_y_stop[int_y_stop %within% x])
x
#>         start                 end eol duration_y_stop
#> 1: 2021-06-01 2021-06-01 00:10:00 E01          2 mins
x_final
#>         start                 end eol duration_y_stop
#> 1: 2021-06-01 2021-06-01 00:10:00 E01           2M 0S       
Mickaël
mickael.canouil.fr | rlille.fr

Jonathan Costa
Messages : 12
Enregistré le : 27 Nov 2017, 16:15

Re: Problème avec la fonction within (lubridate)

Messagepar Jonathan Costa » 21 Oct 2021, 09:22

Bonjour Mickael,

Merci pour votre réponse c'est bon pour moi :)

Bonne journée,

JC


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité