INBO CODING CLUB

28 November 2023

Welcome!

Share your code snippet

If you want to share your code snippet, copy paste your snippet within a section of three backticks (```):

As an example:

library(tidyverse)

(you can copy paste this example and add your code further down)

Yellow sticky notes

No yellow sticky notes online. Put your name + " | " and add a "*" each time you solve a challenge (see below).

Participants

Name Challenges
Damiano Oldoni ***
Pieter Huybrechts ***
Lynn Pallemaerts ***
Margot Vanhellemont **
Rhea Maesele **
Hans Van Calster
Raïsa Carmen ***
Emma Cartuyvels *
Frank Huysentruyt **
Maud Raman
Siebe Indestege ***
Adriaan Seynaeve
Lawrence Whatley
Nele Mullens

Challenge 1

Damiano solution

Pieter's solution


title: "Geese catches in Flanders"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
theme:
version: 4
bootswatch: pulse

library(flexdashboard)
library(tidyverse)    # to do datascience
library(here)         # to work easily with paths
library(geepack)      # to do modelling
library(heatmaply)    # to create interactive heatmaps
library(sf)           # to work with geospatial vector data
library(leaflet)      # to make dynamic maps
library(htmltools)    # to make nice html labels for dynamic maps
catch_fl <- readr::read_csv(
  here::here("data", "20231128", "20231128_geese_counts_cleaned.txt"),
  na = ""
)

Static plots

Column {data-width=650}

per year and province

catch_per_year_province <-
  catch_fl %>%
  group_by(year, province) %>%
  summarize(catched = sum(catched, na.rm = TRUE)) %>%
  ungroup() %>%
  arrange(desc(catched))
ggplot(catch_per_year_province,
       aes(x = year, y = catched, fill = province)) +
  geom_bar(stat = 'identity') +
  scale_x_continuous(breaks = 2012:2018)

Column {.tabset}

per province

catch_per_province <- catch_fl %>%
  group_by(province) %>%
  summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
  ungroup() %>%
  arrange(desc(catched_total))
ggplot(catch_per_province,
       aes(x = province, y = catched_total)) +
  geom_bar(stat = 'identity') +
  scale_x_discrete(breaks = 2012:2018)

per year

catch_per_year <- catch_fl %>%
  group_by(year) %>%
  summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
  ungroup() %>%
  arrange(desc(catched_total))
ggplot(catch_per_year,
       aes(x = year, y = catched_total)) +
  geom_bar(stat = 'identity') +
  scale_x_continuous(breaks = 2012:2018)

Catch analysis at species level

Column {data-width=650}

Catches per year and species

catch_species <-
  catch_fl %>%
  group_by(year, commonName) %>%
  summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
  arrange(commonName)
ggplot(catch_species,
       aes(x = year, y = catched_total, fill = commonName)) +
  geom_bar(stat = 'identity') +
  scale_x_continuous(breaks = 2012:2018)

Column {data-width=650}

# Data modelling
species <- unique(catch_fl$commonName)
model_per_species <-
  purrr::map(
    species,
    function(s) {
      dfs <- catch_fl %>%
        dplyr::filter(commonName == s) %>%
        arrange(location, year) %>%
        mutate(year = as_factor(as.character(year)),
               location = as_factor(location))
      geeglm(counts ~ 0 + year,
             family = poisson,
             data = dfs,
             waves = year,
             id = location)
    })
names(model_per_species) <- species
overview_model <- map(model_per_species, ~summary(.))
overview_gee <- purrr::map2_dfr(
  overview_model,
  names(overview_model), function(model, name) {
    coefficients(model)[,1:2] %>%
      rownames_to_column(var = "year") %>%
      as_tibble() %>%
      mutate(species = name,
             year = str_sub(year, start = 5)) %>%
      dplyr::select(species, everything())
  })
overview_gee <-
  overview_gee %>%
  mutate(
    lwr = exp(Estimate - Std.err),
    upr = exp(Estimate + Std.err),
    Estimate = exp(Estimate)
)

Modelled data

ggplot(overview_gee, aes(x = year, y = Estimate, ymin = lwr, ymax = upr)) +
  geom_errorbar(colour = "cyan3") + geom_point(colour = "cyan4") +
  facet_grid(.~species) +
  xlab("year") + ylab("Estimated number of geese per location") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 9))

Maps

Column {data-width=650}

Heatmap

n_catches_per_location <- catch_fl %>%
  group_by(location) %>%
  summarise(counts = sum(.data$counts, na.rm = TRUE),
            catches = sum(.data$catched, na.rm = TRUE)) %>%
  as.data.frame()
row.names(n_catches_per_location) <- n_catches_per_location$location
n_catches_per_location$location <- NULL
heatmaply(n_catches_per_location, dendrogram = "none")

Column {data-width=650}

Leaflet map

Total number of catches per province

pr_fl <- sf::st_read(
  here::here("data", "20231128" ,"20231128_flemish_provinces.gpkg"),
    quiet = TRUE
)
pr_fl <- pr_fl %>%
  dplyr::left_join(catch_per_province,
                   by = c("TX_PROV_DESCR_NL" = "province"))

#

bins <- seq(0, 6000, by = 1000)
pal <- colorBin("YlOrRd", domain = pr_fl$catched_total, bins = bins)

labels <- sprintf(
  "<strong>%s</strong><br/>%g catches",
  pr_fl$TX_PROV_DESCR_NL, pr_fl$catched_total
) %>% lapply(HTML)

map_catch_pr <- leaflet(pr_fl, width = 750) %>%
  addTiles() %>%
  addPolygons(
    fillColor = ~pal(catched_total),
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlightOptions = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "15px",
      direction = "auto")) %>%
  addLegend(position = "bottomright",
            pal = pal,
            values = ~catched_total)
map_catch_pr

Challenge 2

Pieter's Solution

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)

# Define UI for application that draws a histogram
ui <- fluidPage(

    # Application title
    titlePanel("Catches"),

    # Sidebar with a slider input for number of bins
    sidebarLayout(
        sidebarPanel(
            radioButtons(inputId = "provinces",
                         label = "Province",
                         choices =
                           c("Antwerpen",
                             "Limburg",
                             "Oost-Vlaanderen",
                             "Vlaams-Brabant"),
                         selected = "Oost-Vlaanderen"),
            selectInput(
              inputId = "species",
              label = "Species",
              choices =
                c("Nijlgans",
                  "Grauwe gans",
                  "Soepgans",
                  "Canadese gans",
                  "Brandgans"),
              selected = "Canadese gans"
            )
        ),

        # Show a plot of the generated distribution
        mainPanel(
           textOutput("simple_text")
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  output$simple_text <-
    renderText(paste("You have selected the province",
                   input$provinces,
                   "and the species",
                   input$species))
}

# Run the application
shinyApp(ui = ui, server = server)


Challenge 3

Lynn:

library(shiny)
library(tidyverse)

catch_fl <- readr::read_csv("./data/20231128_geese_counts_cleaned.txt")

# Define UI for application that draws a histogram
ui <- fluidPage(
  
  # Application title
  titlePanel("Geese catches in Flanders"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      radioButtons(inputId = "province",
                   label = "Provincie",
                   choices = c("Vlaams-Brabant", "Antwerpen",
                               "Oost-Vlaanderen",
                               "West-Vlaanderen", "Limburg"),
                   selected = "Oost-Vlaanderen"),
      selectInput(inputId = "species",
                  label = "Soort",
                  choices = c("Brandgans", "Canadese gans",
                              "Grauwe gans",
                              "Nijlgans", "Soepgans"),
                  selected = "Canadese gans")
      ),
    
        # Show a plot of the generated distribution
        mainPanel(
           textOutput("selected_var"),
           plotOutput("catch_per_year")
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  
  output$selected_var <- renderText({ 
    paste0("You have selected ", input$species, " in the province ", input$province, ".")
  })
  
  output$catch_per_year <- renderPlot({
    
    catch_per_year <- catch_fl %>%
      filter(province == input$province) %>%
      filter(commonName == input$species) %>%
      group_by(year) %>%
      summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
      ungroup() %>%
      arrange(desc(catched_total))
    ggplot(catch_per_year,
           aes(x = year, y = catched_total)) +
      geom_bar(stat = 'identity') +
      scale_x_continuous(breaks = 2012:2018)
    
  })

}

# Run the application 
shinyApp(ui = ui, server = server)

Pieter's Solution:

https://pieterhuybrechts.shinyapps.io/my-first-shiny-app/

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(tidyverse)

catch_fl <- read_csv("data/20231128_geese_counts_cleaned.txt", na = "")

# provinces
provinces <- unique(catch_fl$province)
# species
species <- unique(catch_fl$commonName)

# Define UI for application that draws a histogram
ui <- fluidPage(

    # Application title
    titlePanel("Catches"),

    # Sidebar with a slider input for number of bins
    sidebarLayout(
        sidebarPanel(
            radioButtons(inputId = "provinces_radio",
                         label = "Province",
                         choices = provinces,
                         selected = "Oost-Vlaanderen"),
            selectInput(
              inputId = "species_select",
              label = "Species",
              choices = species,
              selected = "Canadese gans"
            )
        ),

        # Show a plot of the generated distribution
        mainPanel(
           textOutput("simple_text"),
           plotOutput("histoplot")
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  output$simple_text <-
    renderText(paste("You have selected the province",
                   input$provinces_radio,
                   "and the species",
                   input$species_select))


  output$histoplot <-
    renderPlot(
      catch_fl %>%
        filter(commonName == input$species_select,
               province == input$provinces_radio) %>%
        group_by(year) %>%
        summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
        ungroup() %>%
        ggplot(aes(x = year, y = catched_total)) +
        geom_bar(stat = 'identity') +
        scale_x_continuous(breaks = 2012:2018) +
        labs(title = paste("Catches of", input$species_select, "in", input$provinces_radio))
    )
}

# Run the application
shinyApp(ui = ui, server = server)


Emma (met crosstalk en flexdashboard):

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
---

```{r setup, include=FALSE}
library(flexdashboard)
library(tidyverse)    # to do datascience
library(here)         # to work easily with paths
library(geepack)      # to do modelling
library(heatmaply)    # to create interactive heatmaps
library(sf)           # to work with geospatial vector data
library(leaflet)      # to make dynamic maps
library(htmltools)    # to make nice html labels for dynamic maps
library(crosstalk)
catch_fl <- readr::read_csv(
  here::here("data", "20231128", "20231128_geese_counts_cleaned.txt"),
  na = ""
)

Overview

Column {data-width=650}

Catch per year and province

catch_per_year_province <-
  catch_fl %>%
  group_by(year, province) %>%
  summarize(catched = sum(catched, na.rm = TRUE)) %>%
  ungroup() %>%
  arrange(desc(catched))
ggplot(catch_per_year_province,
       aes(x = year, y = catched, fill = province)) +
  geom_bar(stat = 'identity') +
  scale_x_continuous(breaks = 2012:2018)

Column {.tabset}

Catch per province

catch_per_province <- catch_fl %>%
  group_by(province) %>%
  summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
  ungroup() %>%
  arrange(desc(catched_total))
ggplot(catch_per_province,
       aes(x = province, y = catched_total)) +
  geom_bar(stat = 'identity') +
  scale_x_discrete(breaks = 2012:2018)

Catch per year

catch_per_year <- catch_fl %>%
  group_by(year) %>%
  summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
  ungroup() %>%
  arrange(desc(catched_total))
ggplot(catch_per_year,
       aes(x = year, y = catched_total)) +
  geom_bar(stat = 'identity') +
  scale_x_continuous(breaks = 2012:2018)

Catch analysis at species level

Column {data-width=650}

Chart 1

catch_species <-
  catch_fl %>%
  group_by(year, commonName) %>%
  summarize(catched_total = sum(catched, na.rm = TRUE)) %>%
  arrange(commonName)
ggplot(catch_species,
       aes(x = year, y = catched_total, fill = commonName)) +
  geom_bar(stat = 'identity') +
  scale_x_continuous(breaks = 2012:2018)

Column {data-width=650}

species <- unique(catch_fl$commonName)
model_per_species <-
  purrr::map(
    species,
    function(s) {
      dfs <- catch_fl %>%
        dplyr::filter(commonName == s) %>%
        arrange(location, year) %>%
        mutate(year = as_factor(as.character(year)),
               location = as_factor(location))
      geeglm(counts ~ 0 + year,
             family = poisson,
             data = dfs,
             waves = year,
             id = location)
    })
names(model_per_species) <- species
overview_model <- map(model_per_species, ~summary(.))
overview_gee <- purrr::map2_dfr(
  overview_model,
  names(overview_model), function(model, name) {
    coefficients(model)[,1:2] %>%
      rownames_to_column(var = "year") %>%
      as_tibble() %>%
      mutate(species = name,
             year = str_sub(year, start = 5)) %>%
      dplyr::select(species, everything())
  })
overview_gee <-
  overview_gee %>%
  mutate(
    lwr = exp(Estimate - Std.err),
    upr = exp(Estimate + Std.err),
    Estimate = exp(Estimate)
)

Chart 2

ggplot(overview_gee, aes(x = year, y = Estimate, ymin = lwr, ymax = upr)) +
  geom_errorbar(colour = "cyan3") + geom_point(colour = "cyan4") +
  facet_grid(.~species) +
  xlab("year") + ylab("Estimated number of geese per location") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 9))

Maps

Column {data-width=650}

Chart 1

n_catches_per_location <- catch_fl %>%
  group_by(location) %>%
  summarise(counts = sum(.data$counts, na.rm = TRUE),
            catches = sum(.data$catched, na.rm = TRUE)) %>%
  as.data.frame()
row.names(n_catches_per_location) <- n_catches_per_location$location
n_catches_per_location$location <- NULL
heatmaply(n_catches_per_location, dendrogram = "none")

Column {data-width=650}

Chart 2

pr_fl <- sf::st_read(
  here::here("data", "20231128" ,"20231128_flemish_provinces.gpkg")
)
pr_fl <- pr_fl %>%
  dplyr::left_join(catch_per_province,
                   by = c("TX_PROV_DESCR_NL" = "province"))

bins <- seq(0, 6000, by = 1000)
pal <- colorBin("YlOrRd", domain = pr_fl$catched_total, bins = bins)

labels <- sprintf(
  "<strong>%s</strong><br/>%g catches",
  pr_fl$TX_PROV_DESCR_NL, pr_fl$catched_total
) %>% lapply(HTML)

map_catch_pr <- leaflet(pr_fl) %>%
  addTiles() %>%
  addPolygons(
    fillColor = ~pal(catched_total),
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlightOptions = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "15px",
      direction = "auto")) %>%
  addLegend(position = "bottomright",
            pal = pal,
            values = ~catched_total)
map_catch_pr

Choose your own adventure

Column {data-width=650}

Choose variables

shared_geese <- SharedData$new(catch_fl)

filter_checkbox(id = "province",
                  label = "Provincie",
                  sharedData = shared_geese,
                  group = ~province)

filter_select(id = "commonName",
              label = "Soort",
              sharedData = shared_geese,
              group = ~commonName)


Column {data-width=650}

Histogram

plot_ly(shared_geese, 
        x = ~year, 
        y = ~counts, 
        color = ~commonName,
        type = "bar") %>%
  layout(barmode = "stack")
Select a repo