Edit du 13/12/2019 : ajout du lien entre direction du vent et autres données.

On souhaite établir un lien entre le nombre de minutes positifs par nuit et les conditions météorologiques pour 4 espèces: PippiT, Pipnat, Nyclei et Nycnoc. On va utiliser les données de Météo France en résumant les données pour chaque nuit (entre le coucher et le lever du soleil).

Aggrégation par nuit

infoclimat_t <- read_rds("climat/infoclimat_t.rds")
med.fact <- function(x) {
  names(which.max(table(x)))
}
climat_per_night <- infoclimat_t %>%
  mutate(direction = direction %% 360) %>%
  mutate(direction = ifelse(vent_heure == 0, NA, direction)) %>%
  mutate(direction = cut_interval(direction, length = 45)) %>%
  filter(coucher < Heure | Heure < lever) %>%
  mutate(day = floor_date(Heure - hours(12), "1 day")) %>%
  group_by(day) %>%
  summarise(Tmin = min(Température),
            Tmax = max(Température),
            Tmean = mean(Température),
            direction = med.fact(direction),
            vent_heure = mean(vent_heure, na.rm = TRUE),
            vent_max = max(vent_max, na.rm = TRUE),
            Pression = mean(Pression),
            Humidité = mean(Humidité),
            Pluie = sum(Pluie))

On va maintenant résumer les contacts sur chaque nuit (pour laquelle l’enregistrement est complet) en calculant le nombre de minutes distinctes où au moins un cri est enregistré.

calls_complete_night <- read_rds("data/calls.rds")
calls_per_night <- calls_complete_night %>%
  mutate(day = floor_date(date - hours(12), "1 day")) %>%
  filter(Id == "PippiT" | Id == "Pipnat" | Id == "Nyclei" | Id == "Nycnoc") %>%
  group_by(Id, day) %>%
  summarise(min_pos = n_distinct(Heure, Minute), contacts = n(),
            calls = sum(NbCris)) %>%
  ungroup()
# Add nights with no contact
calls_per_night <- calls_per_night %>%
  group_by(Id) %>%
  group_modify(~ right_join(., calls_per_night %>% select(day) %>% unique(),
                         by = "day")) %>%
  replace_na(list(min_pos = 0, contacts = 0, calls = 0)) %>%
  ungroup()

Affichons le lien entre l’activité et plusieurs mesures météorologiques.

calls_per_night %>%
  left_join(climat_per_night, by = "day") %>%
  select(-direction) %>%
  gather(climate, measure, Tmin, Tmax, Tmean, vent_heure, vent_max, Pression,
         Humidité, Pluie) %>%
  ggplot(aes(x = measure, y = min_pos)) +
  facet_grid(Id ~ climate, scales = "free") +
  geom_jitter()

Pour simplifier le précédent schéma, il faut étudier le lien entre les mesures météorologiques :

library(GGally)
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## 
## Attaching package: 'GGally'
## The following object is masked from 'package:dplyr':
## 
##     nasa
calls_per_night %>%
  left_join(climat_per_night, by = "day") %>%
  select(day, Tmin, Tmax, Tmean, vent_heure, vent_max, Pression, Humidité,
         Pluie) %>%
  ggpairs()

Observations sur les mesures :

La pression serait donc un facteur confondant.

On va restreindre les mesures pour simplifier le graphiques.

calls_per_night %>%
  left_join(climat_per_night, by = "day") %>%
  gather(climate, measure, day, Tmin, vent_heure, Pression, Humidité) %>%
  group_by(Id, climate) %>%
  mutate(x = cut_number(measure, n = 5)) %>%
  group_by(Id, climate, x) %>%
  mutate(med_min = median(min_pos)) %>%
  ggplot(aes(x = measure, y = min_pos)) +
  facet_grid(Id ~ climate, scales = "free") +
  geom_jitter() +
  geom_smooth(se = FALSE) +
  geom_rug() +
  geom_line(aes(y = med_min), col = "red", size = 1)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Observations sur les effets :

Finalement, on va observer s’il y a un lien entre l’activité et la direction du vent.

calls_per_night %>%
  left_join(climat_per_night, by = "day") %>%
  ggplot(aes(x = direction, y = min_pos)) +
  facet_wrap(Id ~ ., scales = "free") +
  geom_jitter() +
  stat_summary(fun.y = median, fun.ymin = median, fun.ymax = median,
               geom = "crossbar", width = 0.5, col = "red")

Comme la majorité des vents viennent du nord-est, les données sont insuffisantes pour identifier un effet entre la direction du vent et le nombre de minutes positives.

Aggrégation par heure

On va descendre à un grain plus fin (heure) pour avoir plus de données.

calls <- read_csv("data/total - V2.csv", col_types = cols()) %>%
  select(-Temps) %>%
  mutate(Id = ifelse(Id == "Chirosp", "ChiroSp", Id)) %>%
  mutate(Id = ifelse(Id == "cris sociaux", "Cris sociaux", Id)) %>%
  mutate(date = make_datetime(Annee, Mois, Jour, Heure, Minute,
                              tz = "Europe/Paris"))
## Warning: 1 parsing failure.
##   row   col   expected           actual                  file
## 19971 Temps time like  1,19930555555556 'data/total - V2.csv'
calls_per_hour <- calls %>%
  mutate(Heure = ceiling_date(date, "1 hour")) %>%
  filter(Id == "PippiT" | Id == "Pipnat" | Id == "Nyclei" | Id == "Nycnoc") %>%
  group_by(Id, Heure) %>%
  summarise(min_pos = n_distinct(Heure, Minute), contacts = n(),
            calls = sum(NbCris)) %>%
  ungroup()
# Add hours with no contact
calls_per_hour <- calls_per_hour %>%
  group_by(Id) %>%
  group_modify(~ right_join(., calls_per_hour %>% select(Heure) %>% unique(),
                         by = "Heure")) %>%
  replace_na(list(min_pos = 0, contacts = 0, calls = 0)) %>%
  ungroup()

On peut répéter l’analyse des données météorologiques.

climat_per_hour <- infoclimat_t %>%
  mutate(direction = direction %% 360) %>%
  mutate(direction = ifelse(vent_heure == 0, NA, direction)) %>%
  mutate(direction = cut_interval(direction, length = 45))
calls_per_hour %>%
  left_join(climat_per_hour, by = "Heure") %>%
  select(Heure, Température, vent_heure, vent_max, Pression, Humidité,
         Pluie, direction) %>%
  ggpairs()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Effets :

Il est possible que le lien entre humidité et activité soit en fait lié à la température (en tant que facteur confondant).

calls_per_hour %>%
  left_join(climat_per_hour, by = "Heure") %>%
  mutate(vent_heure = jitter(vent_heure)) %>%
  gather(climate, measure, Heure, Température, vent_heure, Pression,
         Humidité) %>%
  group_by(Id, climate) %>%
  mutate(x = cut_number(measure, n = 4)) %>%
  group_by(Id, climate, x) %>%
  mutate(med_min = median(min_pos)) %>%
  ggplot(aes(x = measure, y = min_pos)) +
  facet_grid(Id ~ climate, scales = "free") +
  geom_point() +
  geom_smooth(se = FALSE) +
  geom_rug() +
  geom_line(aes(y = med_min), col = "red", size = 1)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

On confirme que pour PippiT, la température a un effet direct sur l’activité (ainsi qu’une forte humidité et pression), alors que la vitesse du vent ne semble pas avoir d’effet.

calls_per_hour %>%
  left_join(climat_per_hour, by = "Heure") %>%
  ggplot(aes(x = direction, y = min_pos)) +
  facet_wrap(Id ~ ., scales = "free") +
  geom_jitter() +
  geom_boxplot()

La direction du vent ne semble pas avoir d’effet, sauf pour PippiT qui semble avoir plus d’activités en présence d’un vent d’ouest (qui est associé à des températures > 10 °C).

Conclusion

Le seul effet notable dans les données concerne la diminution de l’activité de la pipistrelle commune lorsque les températures sont faibles. Elle ne semble d’ailleurs pas significativement impactée par le vent.

## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.3 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] GGally_1.4.0    tidyr_0.8.3     readr_1.3.1     lubridate_1.7.4
## [5] ggplot2_3.2.0   dplyr_0.8.3    
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.1         RColorBrewer_1.1-2 pillar_1.4.2      
##  [4] compiler_3.6.1     plyr_1.8.4         tools_3.6.1       
##  [7] zeallot_0.1.0      digest_0.6.20      evaluate_0.14     
## [10] tibble_2.1.3       gtable_0.3.0       pkgconfig_2.0.2   
## [13] rlang_0.4.0        yaml_2.2.0         xfun_0.8          
## [16] withr_2.1.2        stringr_1.4.0      knitr_1.23        
## [19] vctrs_0.2.0        hms_0.5.0          grid_3.6.1        
## [22] tidyselect_0.2.5   reshape_0.8.8      glue_1.3.1        
## [25] R6_2.4.0           rmarkdown_1.14     purrr_0.3.2       
## [28] reshape2_1.4.3     magrittr_1.5       scales_1.0.0      
## [31] backports_1.1.4    htmltools_0.3.6    assertthat_0.2.1  
## [34] colorspace_1.4-1   labeling_0.3       stringi_1.4.3     
## [37] lazyeval_0.2.2     munsell_0.5.0      crayon_1.3.4