---
title: "Trend lange-afstand-trekvogels"
date: 2026-03-20T09:30:00+01:00
thema: 
  - Beschermde natuur
  - Flora & fauna
keywords: 
  - soorten
  - trend
  - broedvogels
  - ABV
add_generic:
  - classificatie
lang: nl
tab: indicator
verantwoordelijke: 
  - Glenn Vermeersch <glenn.vermeersch@inbo.be>
  - Thierry Onkelinx <thierry.onkelinx@inbo.be>
output: html_document
---

```{r setup, include=FALSE}
library(crosstalk)
library(effectclass)
library(knitr)
library(git2rdata)
library(htmlwidgets)
library(plotly)
library(scales)
library(tidyverse)
library(INBOtheme)
library(INBOmd)
source(file.path("..", "..", "inbo_theme.R"))
opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
set.seed(20190920)
setWidgetIdSeed(20190920)
options(htmlwidgets.TOJSON_ARGS = list(pretty = TRUE))
conflicted::conflicts_prefer(dplyr::filter, dplyr::pull, plotly::layout,
                             plotly::config)
```

```{r inlezen-gegevens}
soorten <- read_vc("abv_lange_afstand_soorten")
thresholds <- c(soorten$ondergrens[1], soorten$bovengrens[1])
threshold_display <- sprintf(
  "%+.1f%%", 100 * thresholds - 100
)
read_vc("abv_lange_afstand_indicator") %>%
  mutate(
    interpretatie = recode(
      klasse, "++" = "sterke toename", "+" = "toename", "+~" = "matige toename",
      "~" = "stabiel", "-~" = "matige afname", "-" = "afname",
      "--" = "sterke afname", "?+" = "mogelijke toename",
      "?-" = "mogelijke afname", "?" = "onduidelijk", "R" = "referentie"
    )
  ) -> gegevens
```

Lange-afstand-trekkers vertonen een **wisselende index tot 2014**.
Daarna was er een gestage daling tot in 2018. In 2017 en 2018 kan men spreken van een **significante afname ten opzichte van 2007**.
De index vertoont erna weer een schommelend verloop.
In **2024 en 2025** tonen de cijfers een -voorlopig niet verklaarde- **heropleving** tot het niveau van 2007.

```{r plotly, eval = interactive() || opts_knit$get("rmarkdown.pandoc.to") == "html", fig.cap = "Figuur 1: trend lange-afstand-trekvogels"}

gegevens |>
  filter(.data$frequentie == "jaarlijks") -> nadien
nadien |>
  mutate(
    old = .data$referentie, referentie = .data$naar, naar = .data$old,
    schatting = 1 / .data$schatting, old = .data$lcl90, lcl90 = 1 / .data$ucl90,
    ucl90 = 1 / .data$old,
    interpretatie = classification(
      .data$lcl90, .data$ucl90, threshold = thresholds, reference = 1
    ) |>
      as.character() |>
      recode(
        "++" = "sterke toename", "+" = "toename", "+~" = "matige toename",
        "~" = "stabiel", "-~" = "matige afname", "-" = "afname",
        "--" = "sterke afname", "?+" = "mogelijke toename",
        "?-" = "mogelijke afname", "?" = "onduidelijk", "R" = "referentie"
      ),
    wijziging = format_ci(
      .data$schatting, lcl = .data$lcl90, ucl = .data$ucl90, percent = TRUE,
      sign = TRUE, change = TRUE
    )
  ) -> voordien
voordien |>
  bind_rows(
    nadien,
    nadien |>
      distinct(.data$referentie) |>
      mutate(
        naar = .data$referentie, schatting = 1, lcl90 = 1, ucl90 = 1,
        wijziging = "", interpretatie = "referentie"
      )
  ) -> jaarlijks
range(jaarlijks$naar) + c(-1, 1) -> bereik_x
jaarlijks |>
  arrange(.data$referentie, .data$naar
          # , .data$volgorde
          ) |>
  transmute(
    .data$referentie, .data$naar, across(c("schatting", "lcl90", "ucl90"), log),
    sd = (.data$ucl90 - .data$lcl90) / 2 / qnorm(0.95),
    wijziging = sprintf(
      "%.0f t.o.v. %i\n%s\n%s", floor(.data$naar), .data$referentie,
      .data$wijziging, .data$interpretatie
    ) |>
      str_replace_all(".*\n\nreferentie", "referentie"),
    key = sprintf("%.0f-%i", floor(.data$naar), .data$referentie)
  ) |>
  group_by(.data$referentie) |>
  mutate(
    ref_x = rep(bereik_x[2], 3) |>
      c(rep(NA, n() - 3)),
    ref_y = c(0, log(thresholds)) |>
      c(rep(NA, n() - 3)),
    ref_text = c(
      "toestand in", "belangrijke afname t.o.v.", "belangrijke toename t.o.v."
    ) |>
      paste(.data$referentie),
    textposition = c("top left", "bottom left") |>
      rep(n()) |>
      head(n())
  ) |>
  mutate(schatting = ifelse(referentie == naar, NA, schatting),
         ) |>
  SharedData$new(key = ~key) -> index
c(
  index$data(withFilter = FALSE)$lcl90,
  index$data(withFilter = FALSE)$ucl90,
  log(thresholds)
) |>
  range(na.rm = TRUE) -> bereik
change_breaks(n = 5, extra = log(thresholds))(bereik) -> deze_breaks


min_year <- index$data(withFilter = FALSE) %>%
  select(referentie) %>%
  min()
max_year <- index$data(withFilter = FALSE) %>%
  select(referentie) %>%
  max()


ref_final_year <- index$data(withFilter = FALSE) %>%
  filter(referentie == min_year & naar == min_year) %>%
  mutate(referentie = max_year,
         naar = max_year,
         key = paste0(max_year, "-", max_year))

combined_data <- bind_rows(index$data(withFilter = FALSE),
                           ref_final_year)

index <- SharedData$new(combined_data, key = ~key)

bscols(
  widths = c(10, 2),
  plot_ly(index, x = ~naar, y = ~schatting) |>
    add_lines(y = ~schatting, name = "Schatting") |>
    add_ribbons(ymin = ~lcl90,
                ymax = ~ucl90,
                line = list(color = "rgba(40,42,114,0.4)", width = 0.5),
                fillcolor = "rgba(40,42,114,0.4)",
                name = "90% CI",
                showlegend = TRUE) |>
    add_text(x = ~ref_x, y = ~ref_y, text = ~ref_text,
      textposition = ~textposition,
      showlegend = FALSE) |>
    add_trace(x = ~referentie, y = ~0,
              type = "scatter", mode = "markers",
              marker = list(
                color = ~ifelse(referentie == naar, "red", "red"),
                size = ~ifelse(referentie == naar, 14, 0.01),
                line = list(width = 1, color = "black")),
            textfont = list(color = "black", size = 11),
            name = "Referentie",
            showlegend = TRUE) %>%
    layout(legend = list(itemsizing = "constant")) |>
    config(
      displaylogo = FALSE,
      modeBarButtonsToRemove = c(
        "autoScale", "hoverCompareCartesian", "lasso2d", "select2d")) |>
    layout(
      xaxis = list(title = list(font = list(size = 0)), range = bereik_x),
      yaxis = list(
        title = list(font = list(size = 0)), zerolinewidth = 1,
        tickvals = deze_breaks, ticktext = change_labels(deze_breaks)
      ),
      shapes = list(
        type = "rect", x0 = 0, x1 = 1, xref = "paper", y0 = log(thresholds[1]),
        y1 = log(thresholds[2]), line = list(width = 0), opacity = 0.1,
        fillcolor = "black", layer = "below",
        showlegend = FALSE)),
  filter_select(
    id = "ref_jaar", label = "Referentiejaar", sharedData = index,
    group = ~referentie, multiple = FALSE
  )
) %>%
  `class<-`(c(class(.), "htmlwidget"))
```

```{r ggplot, eval = interactive() || opts_knit$get("rmarkdown.pandoc.to") != "html"}
gegevens |>
  filter(
    .data$frequentie == "jaarlijks", .data$referentie == min(.data$referentie)
  ) |>
  mutate(
    across(c("schatting", "lcl90", "ucl90"), log),
    sd = (.data$ucl90 - .data$lcl90) / 2 / qnorm(0.95)
  ) |>
  ggplot(aes(x = naar, y = schatting)) +
  annotate(
    geom = "rect", xmin = -Inf, xmax = Inf, ymin = log(thresholds[1]),
    ymax = log(thresholds[2]), alpha = 0.5, fill = inbo_grijs
  ) +
  geom_line() +
  geom_ribbon(aes(ymin = lcl90, ymax = ucl90),
              fill = inbo_palette(1),
              alpha = 0.4,
              linewidth = 0.5) +
  geom_hline(yintercept = 0, linetype = 2) +
  scale_y_continuous(
    "procentuele wijziging t.o.v. referentieperiode",
    breaks = change_breaks(n = 5, extra = log(thresholds)),
    labels = change_labels
  ) +
  theme(axis.title = element_blank())
```

De blauwe zone stelt het 90% geloofwaardigheidsinterval (CI) voor. Een toename (of afname) is statistisch significant van zodra de referentie onder (of boven) het geloofwaardigheidsinterval ligt. De grijze balk geeft aan vanaf welk percentage er een belangrijke wijziging is ten opzichte van het referentiejaar.

## Definitie

Deze indicator toont, op basis van gegevens uit het project "Algemene Broedvogels Vlaanderen (ABV)", de evolutie van `r nrow(soorten)` soorten broedvogels die in de loop van het najaar uit Vlaanderen wegtrekken en naar Afrika migreren, tot voorbij de Sahara. 
De index berekent de procentuele wijziging t.o.v. een referentiejaar.
De indicator is gebaseerd op het geometrische gemiddelde van de indices van zijn afzonderlijke soorten: `r paste(soorten$soort, sep = ", ")`.

## Bespreking

Sedert 2014 wordt de index enkel berekend op de data bekomen via het speciaal hiervoor ontworpen ABV-meetnet. 
De besproken trends hebben betrekking op de periode 2007-2024.

Lange-afstand-trekkers vertonen een **fluctuerende index tot 2014**.
In 2015 daalt de index tot onder de waarde van 2007.
**Vanaf 2017** is er sprake van een **significante sterke afname**.
Erna vertoont de index weer een schommelend verloop.
De cijfers van **2024 en 2025** tonen een -voorlopig niet verklaarde- **heropleving** tot het niveau van 2007.

```{r sterkste, results = "asis"}
gegevens %>%
  filter(
    frequentie == "jaarlijks", referentie < naar
  ) %>%
  arrange(desc(abs(log(schatting)))) %>%
  slice(1) %>%
  transmute(
    tekst = sprintf(
      "Tussen %i en %i zien we het grootste verschil: %s, \"%s\".",
      referentie, naar, wijziging, interpretatie
    )
  ) %>%
  pull(tekst) %>%
  cat()
```
```{r huidig, results = "asis"}
gegevens %>%
  filter(
    frequentie == "jaarlijks", referentie == min(referentie), naar == max(naar)
  ) %>%
  mutate(
    wijziging = sprintf(
        fmt =
"De aantallen in %i bedragen %s van de aantallen in het referentiejaar %i.
Dit interpreteren we als \"%s\".",
        naar, wijziging, referentie, interpretatie
      )
  ) %>%
  pull(wijziging) %>%
  cat()
```

```{js change-js}
function filter_default() {
  document.getElementById("ref_jaar").getElementsByClassName("selectized")[0].selectize.removeOption("");
  document.getElementById("ref_jaar").getElementsByClassName("selectized") 
[0].selectize.setValue("2007", false);
 }
$(document).ready(filter_default);
```
---
title: "Trend lange-afstand-trekvogels"
date: 2026-03-20T09:30:00+01:00
thema: 
  - Beschermde natuur
  - Flora & fauna
keywords: 
  - soorten
  - trend
  - broedvogels
  - ABV
add_generic:
  - classificatie
lang: nl
tab: indicator
verantwoordelijke: 
  - Glenn Vermeersch <glenn.vermeersch@inbo.be>
  - Thierry Onkelinx <thierry.onkelinx@inbo.be>
output: html_document
---

```{r setup, include=FALSE}
library(crosstalk)
library(effectclass)
library(knitr)
library(git2rdata)
library(htmlwidgets)
library(plotly)
library(scales)
library(tidyverse)
library(INBOtheme)
library(INBOmd)
source(file.path("..", "..", "inbo_theme.R"))
opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
set.seed(20190920)
setWidgetIdSeed(20190920)
options(htmlwidgets.TOJSON_ARGS = list(pretty = TRUE))
conflicted::conflicts_prefer(dplyr::filter, dplyr::pull, plotly::layout,
                             plotly::config)
```

```{r inlezen-gegevens}
soorten <- read_vc("abv_lange_afstand_soorten")
thresholds <- c(soorten$ondergrens[1], soorten$bovengrens[1])
threshold_display <- sprintf(
  "%+.1f%%", 100 * thresholds - 100
)
read_vc("abv_lange_afstand_indicator") %>%
  mutate(
    interpretatie = recode(
      klasse, "++" = "sterke toename", "+" = "toename", "+~" = "matige toename",
      "~" = "stabiel", "-~" = "matige afname", "-" = "afname",
      "--" = "sterke afname", "?+" = "mogelijke toename",
      "?-" = "mogelijke afname", "?" = "onduidelijk", "R" = "referentie"
    )
  ) -> gegevens
```

Lange-afstand-trekkers vertonen een **wisselende index tot 2014**.
Daarna was er een gestage daling tot in 2018. In 2017 en 2018 kan men spreken van een **significante afname ten opzichte van 2007**.
De index vertoont erna weer een schommelend verloop.
In **2024 en 2025** tonen de cijfers een -voorlopig niet verklaarde- **heropleving** tot het niveau van 2007.

```{r plotly, eval = interactive() || opts_knit$get("rmarkdown.pandoc.to") == "html", fig.cap = "Figuur 1: trend lange-afstand-trekvogels"}

gegevens |>
  filter(.data$frequentie == "jaarlijks") -> nadien
nadien |>
  mutate(
    old = .data$referentie, referentie = .data$naar, naar = .data$old,
    schatting = 1 / .data$schatting, old = .data$lcl90, lcl90 = 1 / .data$ucl90,
    ucl90 = 1 / .data$old,
    interpretatie = classification(
      .data$lcl90, .data$ucl90, threshold = thresholds, reference = 1
    ) |>
      as.character() |>
      recode(
        "++" = "sterke toename", "+" = "toename", "+~" = "matige toename",
        "~" = "stabiel", "-~" = "matige afname", "-" = "afname",
        "--" = "sterke afname", "?+" = "mogelijke toename",
        "?-" = "mogelijke afname", "?" = "onduidelijk", "R" = "referentie"
      ),
    wijziging = format_ci(
      .data$schatting, lcl = .data$lcl90, ucl = .data$ucl90, percent = TRUE,
      sign = TRUE, change = TRUE
    )
  ) -> voordien
voordien |>
  bind_rows(
    nadien,
    nadien |>
      distinct(.data$referentie) |>
      mutate(
        naar = .data$referentie, schatting = 1, lcl90 = 1, ucl90 = 1,
        wijziging = "", interpretatie = "referentie"
      )
  ) -> jaarlijks
range(jaarlijks$naar) + c(-1, 1) -> bereik_x
jaarlijks |>
  arrange(.data$referentie, .data$naar
          # , .data$volgorde
          ) |>
  transmute(
    .data$referentie, .data$naar, across(c("schatting", "lcl90", "ucl90"), log),
    sd = (.data$ucl90 - .data$lcl90) / 2 / qnorm(0.95),
    wijziging = sprintf(
      "%.0f t.o.v. %i\n%s\n%s", floor(.data$naar), .data$referentie,
      .data$wijziging, .data$interpretatie
    ) |>
      str_replace_all(".*\n\nreferentie", "referentie"),
    key = sprintf("%.0f-%i", floor(.data$naar), .data$referentie)
  ) |>
  group_by(.data$referentie) |>
  mutate(
    ref_x = rep(bereik_x[2], 3) |>
      c(rep(NA, n() - 3)),
    ref_y = c(0, log(thresholds)) |>
      c(rep(NA, n() - 3)),
    ref_text = c(
      "toestand in", "belangrijke afname t.o.v.", "belangrijke toename t.o.v."
    ) |>
      paste(.data$referentie),
    textposition = c("top left", "bottom left") |>
      rep(n()) |>
      head(n())
  ) |>
  mutate(schatting = ifelse(referentie == naar, NA, schatting),
         ) |>
  SharedData$new(key = ~key) -> index
c(
  index$data(withFilter = FALSE)$lcl90,
  index$data(withFilter = FALSE)$ucl90,
  log(thresholds)
) |>
  range(na.rm = TRUE) -> bereik
change_breaks(n = 5, extra = log(thresholds))(bereik) -> deze_breaks


min_year <- index$data(withFilter = FALSE) %>%
  select(referentie) %>%
  min()
max_year <- index$data(withFilter = FALSE) %>%
  select(referentie) %>%
  max()


ref_final_year <- index$data(withFilter = FALSE) %>%
  filter(referentie == min_year & naar == min_year) %>%
  mutate(referentie = max_year,
         naar = max_year,
         key = paste0(max_year, "-", max_year))

combined_data <- bind_rows(index$data(withFilter = FALSE),
                           ref_final_year)

index <- SharedData$new(combined_data, key = ~key)

bscols(
  widths = c(10, 2),
  plot_ly(index, x = ~naar, y = ~schatting) |>
    add_lines(y = ~schatting, name = "Schatting") |>
    add_ribbons(ymin = ~lcl90,
                ymax = ~ucl90,
                line = list(color = "rgba(40,42,114,0.4)", width = 0.5),
                fillcolor = "rgba(40,42,114,0.4)",
                name = "90% CI",
                showlegend = TRUE) |>
    add_text(x = ~ref_x, y = ~ref_y, text = ~ref_text,
      textposition = ~textposition,
      showlegend = FALSE) |>
    add_trace(x = ~referentie, y = ~0,
              type = "scatter", mode = "markers",
              marker = list(
                color = ~ifelse(referentie == naar, "red", "red"),
                size = ~ifelse(referentie == naar, 14, 0.01),
                line = list(width = 1, color = "black")),
            textfont = list(color = "black", size = 11),
            name = "Referentie",
            showlegend = TRUE) %>%
    layout(legend = list(itemsizing = "constant")) |>
    config(
      displaylogo = FALSE,
      modeBarButtonsToRemove = c(
        "autoScale", "hoverCompareCartesian", "lasso2d", "select2d")) |>
    layout(
      xaxis = list(title = list(font = list(size = 0)), range = bereik_x),
      yaxis = list(
        title = list(font = list(size = 0)), zerolinewidth = 1,
        tickvals = deze_breaks, ticktext = change_labels(deze_breaks)
      ),
      shapes = list(
        type = "rect", x0 = 0, x1 = 1, xref = "paper", y0 = log(thresholds[1]),
        y1 = log(thresholds[2]), line = list(width = 0), opacity = 0.1,
        fillcolor = "black", layer = "below",
        showlegend = FALSE)),
  filter_select(
    id = "ref_jaar", label = "Referentiejaar", sharedData = index,
    group = ~referentie, multiple = FALSE
  )
) %>%
  `class<-`(c(class(.), "htmlwidget"))
```

```{r ggplot, eval = interactive() || opts_knit$get("rmarkdown.pandoc.to") != "html"}
gegevens |>
  filter(
    .data$frequentie == "jaarlijks", .data$referentie == min(.data$referentie)
  ) |>
  mutate(
    across(c("schatting", "lcl90", "ucl90"), log),
    sd = (.data$ucl90 - .data$lcl90) / 2 / qnorm(0.95)
  ) |>
  ggplot(aes(x = naar, y = schatting)) +
  annotate(
    geom = "rect", xmin = -Inf, xmax = Inf, ymin = log(thresholds[1]),
    ymax = log(thresholds[2]), alpha = 0.5, fill = inbo_grijs
  ) +
  geom_line() +
  geom_ribbon(aes(ymin = lcl90, ymax = ucl90),
              fill = inbo_palette(1),
              alpha = 0.4,
              linewidth = 0.5) +
  geom_hline(yintercept = 0, linetype = 2) +
  scale_y_continuous(
    "procentuele wijziging t.o.v. referentieperiode",
    breaks = change_breaks(n = 5, extra = log(thresholds)),
    labels = change_labels
  ) +
  theme(axis.title = element_blank())
```

De blauwe zone stelt het 90% geloofwaardigheidsinterval (CI) voor. Een toename (of afname) is statistisch significant van zodra de referentie onder (of boven) het geloofwaardigheidsinterval ligt. De grijze balk geeft aan vanaf welk percentage er een belangrijke wijziging is ten opzichte van het referentiejaar.

## Definitie

Deze indicator toont, op basis van gegevens uit het project "Algemene Broedvogels Vlaanderen (ABV)", de evolutie van `r nrow(soorten)` soorten broedvogels die in de loop van het najaar uit Vlaanderen wegtrekken en naar Afrika migreren, tot voorbij de Sahara. 
De index berekent de procentuele wijziging t.o.v. een referentiejaar.
De indicator is gebaseerd op het geometrische gemiddelde van de indices van zijn afzonderlijke soorten: `r paste(soorten$soort, sep = ", ")`.

## Bespreking

Sedert 2014 wordt de index enkel berekend op de data bekomen via het speciaal hiervoor ontworpen ABV-meetnet. 
De besproken trends hebben betrekking op de periode 2007-2024.

Lange-afstand-trekkers vertonen een **fluctuerende index tot 2014**.
In 2015 daalt de index tot onder de waarde van 2007.
**Vanaf 2017** is er sprake van een **significante sterke afname**.
Erna vertoont de index weer een schommelend verloop.
De cijfers van **2024 en 2025** tonen een -voorlopig niet verklaarde- **heropleving** tot het niveau van 2007.

```{r sterkste, results = "asis"}
gegevens %>%
  filter(
    frequentie == "jaarlijks", referentie < naar
  ) %>%
  arrange(desc(abs(log(schatting)))) %>%
  slice(1) %>%
  transmute(
    tekst = sprintf(
      "Tussen %i en %i zien we het grootste verschil: %s, \"%s\".",
      referentie, naar, wijziging, interpretatie
    )
  ) %>%
  pull(tekst) %>%
  cat()
```
```{r huidig, results = "asis"}
gegevens %>%
  filter(
    frequentie == "jaarlijks", referentie == min(referentie), naar == max(naar)
  ) %>%
  mutate(
    wijziging = sprintf(
        fmt =
"De aantallen in %i bedragen %s van de aantallen in het referentiejaar %i.
Dit interpreteren we als \"%s\".",
        naar, wijziging, referentie, interpretatie
      )
  ) %>%
  pull(wijziging) %>%
  cat()
```

```{js change-js}
function filter_default() {
  document.getElementById("ref_jaar").getElementsByClassName("selectized")[0].selectize.removeOption("");
  document.getElementById("ref_jaar").getElementsByClassName("selectized") 
[0].selectize.setValue("2007", false);
 }
$(document).ready(filter_default);
```
