Je vais essayer d'expliquer clairement mon problème.
Je possède deux df :
- "effech" qui correspond à un effort d'échantillonnage mis en place pour suivre des individus par caméra-pièges. Il consiste en un nom de caméra ("cam") et une heure de début d'échantillonnage ("start"). Ce df comporte quelques 30.000 lignes (20 caméras, 1 mois de suivi et une photo toutes les heures).
A ce df j'ai d'ores et déjà associé une aire de détection propre, d'une part, à chaque caméra (calculée sur le terrain), et, d'autre part, entre le jour et la nuit (car la caméra détecte de moins loin la nuit), avec la fonction suivante :
Code : Tout sélectionner
for(i in 1: nrow(effech)){
if((hour(effech[i,"start"]) %in% c(19:23,0:6))) {
effech[i,"aire"] <- airejrnuit$aire[which(airejrnuit$condition=="nuit"&airejrnuit$cam==effech[i, "cam"])]
} else {
effech[i,"aire"] <- airejrnuit$aire[which(airejrnuit$condition=="jour"&airejrnuit$cam==effech[i, "cam"])]
}
}
avec airejrnuit un autre df avec des valeurs d'aire de détection pour chaque caméra en fonction du jour ou de la nuit ("condition").
- "airebrume" correspond à des aires de détection réduites, dans certains intervalles de temps, pour certaines caméras. En fait, l'équipe a, à la main, noté les intervalles de temps lorsqu'il y avait du brouillard, pour chaque caméra et attribué une autre distance de détection. Ce df est composé de "cam" (nom de caméra), "heure_debut" (début de l'intervalle de temps), "heure_fin" (fin de l'intervalle de temps) et "aire" (aire réduite avec la brume).
Ce que je veux faire :
À partir de mon df effech, je voudrais attribuer, dans une nouvelle colonne "aire_2", pour un effort d'échantillonnage particulier si celui-ci se trouve dans un intervalle de temps dans "airebrume", et pour la bonne caméra "cam", l'aire de "airebrume" du bon intervalle/caméra, et remettre l'aire initiale (de effech) si le temps considéré n'est pas dans un intervalle de temps avec de la brume.
Ce que j'ai essayé de faire :
J'ai d'abord essayé de reprendre l'idée de ma première fonction, qui marchait très bien, en la modifiant :
Code : Tout sélectionner
for(i in 1:nrow(effech)) {
if(sum((effech[i,"start"]) %within% interval(ymd_hms(airebrume$date_debut), ymd_hms(airebrume$date_fin)))>0)
{
effech[i,"aire_2"] <- airebrume$aire[which(airebrume$cam==effech[i, "cam"])]
} else {
effech[i,"aire_2"] <- effech[i,"aire"]}
}
Je reçois ce message d'erreur : "Error in `[<-.data.frame`(`*tmp*`, i, "aire_2", value = c(3, : replacement has 4 rows, data has 1". Ce que je comprends, car il se retrouve avec les 4 lignes de airebrume pour la caméra correspondante à attribuer à une seule ligne dans effech et il ne sait pas laquelle choisir.
J'ai donc fait des tentatives comme ci-après pour essayer de lui faire comprendre de prendre la ligne de airebrume correspondante à l'intervalle testé, mais ça ne marche pas ("Error in x[[jj]][iseq] <- vjj : replacement has length zero") et ça prend beaucoup de temps. Pour ce dernier point, j'aimerai bien aussi qu'il ne teste déjà qu'avec le nom de la même caméra de effech dans airebrume pour que ça prenne moins de temps (mon jeu de données complet est très conséquent), si jamais....
Code : Tout sélectionner
for(i in 1:nrow(effech)) {
for(t in 1:nrow(airebrume)){
x<-interval(ymd_hms(airebrume[t,"date_debut"]), ymd_hms(airebrume[t,"date_fin"]))
if(sum((effech[i,"start"]) %within% x)>0)
{
effech[i,"aire_2"] <- airebrume[x, "aire"][which(airebrume[x, "cam"]==effech[i, "cam"])]
} else {
effech[i,"aire_2"] <- effech[i,"aire"]}
}
}
Enfin, j'ai essayé de faire sans boucle mais je reçois un message indiquant que mes vecteurs de remplacement ne sont pas des multiples des vecteurs initiaux, et donc j'ai un résultat mais les valeurs sont attribuées "en boucle" et ça n'a pas de sens. À nouveau, je n'arrive pas à lui faire comprendre de prendre la ligne correspondant à l'intervalle testé.
Code : Tout sélectionner
effech %>% group_by(cam) %>% mutate(aire_2 =
ifelse((sum(effech$start %within% interval(ymd_hms(airebrume$date_debut), ymd_hms(airebrume$date_fin))>0) & (airebrume$cam==effech$cam)), airebrume$aire, effech$aire))
Je sollicite donc votre aide ! j'espère que j'ai été claire (quitte à être longue...)
En vous remerciant par avance :)
Recréer les df effech et airebrume (versions simplifiées, et avec déjà l'aire jour/nuit pour effech) :
Code : Tout sélectionner
library(dplyr)
effech<-data.frame("cam" = c("1_2023", "1_2023", "1_2023", "1_2023", "2_2023", "2_2023", "2_2023", "2_2023"), "start" = c("2023-11-12 16:00:00", "2023-11-15 23:00:00", "2023-11-23 05:00:00", "2023-11-26 06:00:00", "2023-11-23 09:00:00", "2023-12-03 08:00:00", "2023-12-04 20:00:00", "2023-11-29 05:00:00"), "aire" = c(829, 207, 207, 207, 1624, 1624, 33, 33))
effech$start=as.POSIXct(effech$start, format="%Y-%m-%d %H:%M:%S", tz="GMT")
airebrume<-data.frame("cam" = c("1_2023", "1_2023", "1_2023", "1_2023", "2_2023", "2_2023", "2_2023", "2_2023"), "date_debut" = c("2023-11-15 22:01:00", "2023-11-21 22:01:00", "2023-11-17 13:01:00", "2023-11-25 22:01:00", "2023-11-28 22:01:00", "2023-11-30 22:01:00", "2023-12-03 13:01:00", "2023-12-04 22:01:00"), "date_fin" = c("2023-11-16 07:30:00", "2023-11-22 07:30:00", "2023-11-17 16:30:00", "2023-11-26 07:30:00", "2023-11-29 07:30:00", "2023-12-01 07:30:00", "2023-12-03 16:30:00", "2023-12-05 07:30:00"), "aire" = c(3, 3, 75, 3, 8, 8, 48, 8))
airebrume$date_debut=as.POSIXct(airebrume$date_debut, format="%Y-%m-%d %H:%M:%S", tz="GMT")
airebrume$date_fin=as.POSIXct(airebrume$date_fin, format="%Y-%m-%d %H:%M:%S", tz="GMT")