--- title: "Spatial Phenological Patterns" author: - Matthias Templ^[University of Applied Sciences Northwestern Switzerland (FHNW)] - Barbara Templ^[Swiss Federal Institute for Forest, Snow and Landscape Research (WSL)] date: "`r Sys.Date()`" output: rmarkdown::html_vignette bibliography: references.bib vignette: > %\VignetteIndexEntry{Spatial Phenological Patterns} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- *Vignette 4 of 4 for the **pep725** R package. The most current version is available on [GitHub](https://github.com/matthias-da/pep725) and [CRAN](https://CRAN.R-project.org/package=pep725).* ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ``` ## Introduction Phenological timing varies systematically across space due to environmental gradients. Understanding these spatial patterns is fundamental to phenological research because it allows us to: - **Scale observations**: Extrapolate from point measurements to landscapes - **Predict impacts**: Forecast how climate change will shift phenological timing - **Design networks**: Optimize monitoring station placement - **Validate models**: Compare observed gradients with model predictions This vignette covers spatial analysis and visualization functions in the `pep725` package, organized into four parts: ### What You'll Learn | Section | Key Concepts | Functions | |---------|--------------|-----------| | Part 1: Gradients | How phenology changes with altitude & latitude | `pheno_gradient()` | | Part 2: Synchrony | Spatial coherence of phenological events | `pheno_synchrony()` | | Part 3: Combined | Integrating gradient and synchrony results | `pheno_gradient()`, `pheno_synchrony()` | | Part 4: Mapping | Visualizing station networks and patterns | `pheno_leaflet()`, `pheno_map()` | ### Prerequisites This vignette assumes you have completed the "Getting Started" vignette and are familiar with: - The basic structure of PEP725 data - BBCH phenological phase codes - Day of Year (DOY) as a timing metric ## Setup ```{r setup, message=FALSE, warning=FALSE} library(pep725) library(data.table) library(ggplot2) # Download the synthetic dataset pep <- pep_download() # Overview of the data cat("Stations:", length(unique(pep$s_id)), "\n") cat("Altitude range:", min(pep$alt, na.rm = TRUE), "-", max(pep$alt, na.rm = TRUE), "m\n") cat("Latitude range:", round(min(pep$lat, na.rm = TRUE), 2), "-", round(max(pep$lat, na.rm = TRUE), 2), "N\n") ``` --- # Part 1: Phenological Gradients ## What are Phenological Gradients? A **phenological gradient** describes systematic changes in the timing of biological events along an environmental axis. Such gradients reflect spatial variations in climatic conditions and are fundamental for understanding large-scale patterns in phenology. The two most important phenological gradients are associated with elevation and latitude: ### Altitudinal Gradient With increasing elevation, air temperature generally decreases. As a result, phenological events tend to occur progressively later at higher altitudes. The rate at which phenological timing shifts with elevation is commonly referred to as the **phenological lapse rate**. ``` Mountain Profile /\ / \ <- Higher elevation = LATER phenology / \ / \ ____________/ \____________ ^ ^ Earlier Earlier (lowland) (lowland) ``` **Typical values**: In temperate regions of Europe, phenological phases are delayed by **2-4 days per 100 meters** of elevation gain. In practical terms: - A station at 500m elevation might observe flowering 10-20 days later than a lowland station. - High-elevation stations (2000m+) can exhibit delays of 40-80 days relative to lowland sites ### Latitudinal Gradient Moving northward in the Northern Hemisphere is generally associated with cooler climatic conditions and changes in seasonal radiation regimes. Consequently, phenological events tend to occur later at higher latitudes. **Typical values**: Across Europe, phenology is delayed by **2-5 days per degree of latitude** toward the north. For example: - The latitudinal difference between southern France (43°N) and northern Germany (54°N) is about 11 degrees - This corresponds to an expected difference of 22-55 days in phenology ### Why Study Gradients? Understanding phenological gradients is valuable for several reasons: 1. **Scaling observations**: Gradients allow phenological timing to be extrapolated to locations without direct observations, based on elevation or latitude 2. **Validating models**: Phenological and crop models should reproduce observed spatial gradients 3. **Detecting change**: Temporal changes in the strength or shape of phenological gradients may signal climate-driven alterations in biological responses 4. **Understanding adaptation**: Systematic deviations from expected gradients may reveal local adaptation, genetic variation or the influence of site-specific factors. ## Altitudinal Gradient Analysis Let's calculate the elevational gradient for apple flowering: ```{r gradient-altitude} # Calculate elevational gradient for apple flowering grad_alt <- pheno_gradient( pep = pep, variable = "alt", species = "Malus domestica", phase_id = 60, method = "robust" ) print(grad_alt) ``` ### Understanding the Function Parameters | Parameter | Purpose | Your Choice | |-----------|---------|-------------| | `pep` | Input data | Your phenological dataset | | `variable` | Environmental gradient | `"alt"` for elevation, `"lat"` for latitude | | `species` | Species to analyze | Must match exactly (e.g., "Malus domestica") | | `phase_id` | BBCH phase code | 60 = flowering | | `method` | Regression method | `"robust"` recommended for phenological data | ### Interpreting the Results The output contains several important metrics: | Metric | What It Tells You | How to Interpret | |--------|-------------------|------------------| | `slope` | Days delay per 100m elevation | The phenological lapse rate | | `intercept` | Predicted DOY at 0m altitude | Theoretical baseline (extrapolation) | | `r_squared` | Proportion of variance explained | How well elevation predicts phenology | | `n_points` | Number of stations used | Sample size (affects reliability) | **Key interpretation points:** - **Positive slope**: Later phenology at higher elevations (expected) - **Negative slope**: Earlier phenology at higher elevations (unusual - investigate!) - **Slope magnitude**: Compare to literature values (2-4 days/100m typical) - **R-squared**: Values > 0.3 indicate meaningful gradient; < 0.1 suggests weak control ## Latitudinal Gradient Analysis The same function works for latitude gradients: ```{r gradient-latitude} # Calculate latitude gradient grad_lat <- pheno_gradient( pep = pep, variable = "lat", species = "Malus domestica", phase_id = 60, method = "robust" ) print(grad_lat) ``` ## Comparing Regression Methods The `pheno_gradient()` function offers three regression methods. Choosing the right method matters because phenological data often contains outliers. ```{r gradient-methods} # Robust regression (default) - handles outliers grad_robust <- pheno_gradient(pep, variable = "alt", species = "Malus domestica", phase_id = 60, method = "robust") # Ordinary least squares grad_ols <- pheno_gradient(pep, variable = "alt", species = "Malus domestica", phase_id = 60, method = "ols") cat("Robust slope:", round(grad_robust$summary$slope, 2), "days/100m\n") cat("OLS slope:", round(grad_ols$summary$slope, 2), "days/100m\n") ``` ### Which Method Should You Use? | Method | Strengths | Weaknesses | When to Use | |--------|-----------|------------|-------------| | `robust` | Resistant to outliers and leverage points | Slightly lower efficiency under ideal conditions (clean data) | Recommended **default choice** for phenological data | | `ols` | Efficient when assumptions are met | Highly sensitive to outliers | Use after careful data screening | | `quantile` | Models conditional medians or other quantiles | Less precise estimates (wider confidence intervals) | When focusing on median responses | **Recommendation**: Start with `method = "robust"` for exploratory and applied analyses. Substantial differences between robust and OLS estimates often indicate influential observations and should prompt further inspection. ### Comparing Species: Grapevine Gradient Different species may show different gradient strengths. Let's compare apple with grapevine: ```{r gradient-vine} # Calculate gradient for grapevine vine_data <- pep[species == "Vitis vinifera"] # Verify data exists before analysis if (nrow(vine_data) > 0) { grad_vine <- pheno_gradient( pep = pep, variable = "alt", species = "Vitis vinifera", phase_id = 65, # Full flowering method = "robust" ) cat("Comparison of elevation gradients:\n") cat("Apple: ", round(grad_robust$summary$slope, 2), "days/100m", "(R² =", round(grad_robust$summary$r_squared, 3), ")\n") cat("Grapevine: ", round(grad_vine$summary$slope, 2), "days/100m", "(R² =", round(grad_vine$summary$r_squared, 3), ")\n") } else { cat("No grapevine data available for gradient analysis.\n") } ``` ## Gradients by Region Phenological gradients are not uniform across space. Their magnitude and shape can vary between regions due to: - Different climate zones - Local adaptation of species - Data quality differences Estimating gradients separately for different regions: ```{r gradient-by-region} # Calculate gradient by country grad_by_country <- pheno_gradient( pep = pep, variable = "alt", species = "Malus domestica", phase_id = 60, by = "country", method = "robust" ) print(grad_by_country$summary) ``` **What to look for:** - Consistency of slopes: Are slopes consistent across regions? Similar slope estimates across regions suggest a robust and generalizable gradient pattern. - Explained variance: Are R-squared values similar? (Comparable R-squared values indicate that the gradient explains phenological variability consistently across regions.) - Sample size adequacy: Do sample sizes support reliable estimates? (Reliable gradient estimates require sufficient data coverage; small sample sizes (e.g. n < 20) should be interpreted with caution.) ## Visualizing Gradients Visualization plays a key role in interpreting and communicating phenological gradients, helping to assess linearity, uncertainty, and regional differences at a glance: ```{r gradient-plot, fig.height=5} # Plot the gradient relationship if (!is.null(grad_alt$data) && nrow(grad_alt$data) > 2) { p <- plot(grad_alt) print(p) } ``` **Reading the plot:** - Each point represents a station-level mean phenophase (averaged across years). - The fitted line shows the estimated relationship between phenophase and elevation. - Points deviating strongly from the line indicate locations where elevation alone explains phenology poorly. - Systematic clustering of residuals may point to regional influences or additional controlling factors. ## Expected Values and Troubleshooting ### Reference Values from Literature The following table summarises phenological gradient values reported in the literature. These can serve as benchmarks when interpreting your own results: | Gradient | Typical Range | Region | Sources | |----------|---------------|--------|---------| | Altitude | 2–4 days/100m | Europe (temperate) | Pellerin et al. (2012); Vitasse et al. (2009); Ziello et al. (2009) | | Altitude | 1–3 days/100m | Europe (warm / low elevation) | Vitasse et al. (2009); Ziello et al. (2009) | | Latitude | 2–4 days/degree | Europe | Rötzer & Chmielewski (2001) | | Latitude | 3–5 days/degree | North America | Hopkins (1918); Richardson et al. (2019) | **Notes:** - Altitude gradients are reported as delay in days per 100 m of elevation gain. Values vary by species: deciduous broadleaves (e.g. oak, hazel) tend toward the upper end, while conifers (e.g. spruce) show weaker responses (Ziello et al. 2009). - Latitude gradients are reported as delay in days per degree northward. Hopkins' (1918) bioclimatic law predicts approximately 4 days per degree of latitude, which remains a useful first approximation. - Gradient strength may change over time: Chen et al. (2018) showed that altitude gradients in Europe have been declining since the 1980s, indicating more uniform phenology across elevations under warming. **Key references:** - Pellerin, M. et al. (2012). Spring tree phenology in the Alps. *European Journal of Forest Research*, 131, 1957–1965. [doi:10.1007/s10342-012-0646-1](https://doi.org/10.1007/s10342-012-0646-1) - Vitasse, Y. et al. (2009). Leaf phenology sensitivity to temperature in European trees. *Agricultural and Forest Meteorology*, 149, 735–744. [doi:10.1016/j.agrformet.2008.10.019](https://doi.org/10.1016/j.agrformet.2008.10.019) - Ziello, C. et al. (2009). Influence of altitude on phenology of selected plant species in the Alpine region. *Climate Research*, 39, 227–234. [doi:10.3354/cr00822](https://doi.org/10.3354/cr00822) - Rötzer, T. & Chmielewski, F.-M. (2001). Phenological maps of Europe. *Climate Research*, 18, 249–257. [doi:10.3354/cr018249](https://doi.org/10.3354/cr018249) - Richardson, A.D. et al. (2019). Testing Hopkins' Bioclimatic Law with PhenoCam data. *Applications in Plant Sciences*, 7, e01228. [doi:10.1002/aps3.1228](https://doi.org/10.1002/aps3.1228) - Chen, L. et al. (2018). Spring phenology at different altitudes is becoming more uniform under global warming in Europe. *Global Change Biology*, 24, 3969–3975. [doi:10.1111/gcb.14288](https://doi.org/10.1111/gcb.14288) ### When Your Results Differ from Expected | Observation | Possible Causes | What to Do | |-------------|-----------------|------------| | Slope too steep (>5 days/100m) | Outliers, microclimate effects | Check for data errors, use robust method | | Slope too shallow (<1 day/100m) | Limited elevation range, species adaptation | Expand geographic scope | | Negative slope | Data errors, southern aspect effects | Investigate unusual observations | | Very low R² | Other factors dominate (precipitation, soil) | Consider multiple regression | --- # Part 2: Phenological Synchrony ## What is Phenological Synchrony? **Phenological synchrony** describes the degree to which phenological events occur at similar times across different locations within a region during a given period. It addresses the question: Do stations experience the same phenological phase at roughly the same time? ### Visualizing Synchrony Concepts ``` High Synchrony (SD = 5 days) Low Synchrony (SD = 25 days) Station A: ●────────● Station A: ●────────● Station B: ●────────● Station B: ●────────● Station C: ●────────● Station C: ●────────● Station D: ●────────● Station D: ●────────● ▲ ▲ All stations flower Stations flower at within ~10 day window very different times ``` ### Why Study Synchrony? 1. **Ecosystem coherence**: High synchrony suggests strong regional climate control, whereas low synchrony indicates a greater influence of local factors. 2. **Monitoring network design**: When synchrony is high, fewer stations may be sufficient to characterize a region; low synchrony implies the need for denser observation networks. 3. **Detection of change**: Temporal changes in synchrony can indicate shifts in climate variability, increasing spatial heterogeneity, or emerging local adaptations. 4. **Ecological consequences**: Synchrony influences ecological interactions such as pollination, pest dynamics, and trophic mismatch. ## Calculating Synchrony The `pheno_synchrony()` function calculates several metrics to quantify spatial variability: ```{r synchrony-basic} # Calculate synchrony by country and year sync <- pheno_synchrony( pep = pep, species = "Malus domestica", phase_id = 60, by = c("country", "year"), min_stations = 3 ) print(sync) ``` ### Understanding the Parameters | Parameter | Purpose | Typical Values | |-----------|---------|----------------| | `pep` | Input dataset | Phenological dataset prepared with `pep725` | | `species` | Species to analyze | Single species for clear interpretation | | `phase_id` | Phenophase coded by the BBCH-scale (Meier, 2018) | e.g. 60 (flowering), 65 (full flowering) | | `by` | Grouping variables | `c("country", "year")` for regional, year-specific analysis | | `min_stations` | Minimum number of stations per group | 3-5 as a lower bound; 10+ recommended for robust estimates | | `compute_trend` | Estimate temporal trends in synchrony | TRUE (default) when assessing changes over time | ## Understanding Synchrony Metrics Different synchrony metrics capture complementary aspects of spatial variability. Selecting an appropriate metric depends on the analysis goal and data characteristics: | Metric | Formula | Interpretation | When to Use | |--------|---------|----------------|-------------| | `sd_doy` | Standard deviation of day-of-year | Absolute variability in days | Comparing synchrony across phases or regions | | `cv_pct` | (SD/mean) × 100 | Relative variability | Comparing phases with different mean timing | | `range_doy` | Maximum minus minimum doy | Total observed spread | Assessing extreme differences | | `iqr_doy` | 75th - 25th percentile | Robust measure of spread | Preferred when outliers are present | **Interpretation guide:** The following table provides a rule-of-thumb interpretation of synchrony based on the standard deviation of phenological timing across stations. Thresholds are indicative and should be interpreted in relation to species, phenophase, and spatial extent: | SD Value | Interpretation | |----------|----------------| | < 5 days | Very high synchrony; stations behave very similarly | | 5-10 days | Moderate synchrony; regional pattern dominates | | 10-20 days | Low synchrony; local variability is substantial | | > 20 days | Very low synchrony; local factors dominate | ```{r synchrony-summary} summary(sync) ``` ## Temporal Trends in Synchrony An important question in phenological analysis is whether spatial synchrony changes over time. - **Decreasing synchrony**: means growing spatial heterogeneity, for example due to more variable weather or diverging local conditions. - **Increasing synchrony**: suggests stronger regional coherence, potentially driven by a common climate signal overriding local factors ```{r synchrony-trend} # Check if trend analysis was performed if (!is.null(sync$trend) && nrow(sync$trend) > 0) { cat("Trend Analysis Results:\n") print(sync$trend) # Interpret significant trends sig_trends <- sync$trend[!is.na(significant) & significant == TRUE] if (nrow(sig_trends) > 0) { cat("\nSignificant trends detected:\n") print(sig_trends[, .(country, slope, direction, p_value)]) } } ``` ### Interpreting Trend Results | Trend Direction | Interpretation | Ecological meaning | |-----------------|---------------|-------------------------| | Decreasing SD | Increasing synchrony | Phenological timing becoming more spatially coherent | | Increasing SD | Decreasing synchrony | Growing spatial variability among stations | | No trend | Stable synchrony | Persistent spatial patterns over time | **Cautions with trend interpretation:** - Changes in the observation network (e.g. stations added or removed) can introduce artificial trends. - Reliable trend detection typically requires at least 15–20 years of data. - Statistical significance should be interpreted alongside ecological relevance and effect size. ## Visualizing Synchrony Over Time ```{r synchrony-plot, fig.height=5} # Plot synchrony time series if (nrow(sync$data[!is.na(sd_doy)]) > 5) { p <- plot(sync) print(p) } ``` **Reading the plot:** - Y-axis shows the synchrony metric (typically the SD of timing) - The fitted trend line indicates long-term change - Scatter around trend reflects year-to-year variability in synchrony ## Synchrony Without Trend Analysis For exploratory analyses or descriptive summaries, synchrony can be calculated without estimating temporal trends: ```{r synchrony-simple} sync_simple <- pheno_synchrony( pep = pep, species = "Malus domestica", phase_id = 60, by = c("country", "year"), min_stations = 3, compute_trend = FALSE ) # Just the synchrony data head(sync_simple$data) ``` This approach is useful for rapid assessment or when time series length is insufficient for robust trend estimation. ### Comparing Synchrony: Grapevine vs. Apple Different species may show different synchrony levels due to their biology: ```{r synchrony-compare} # Calculate synchrony for grapevine vine_check <- pep[species == "Vitis vinifera" & phase_id == 65] if (nrow(vine_check) > 0) { sync_vine <- pheno_synchrony( pep = pep, species = "Vitis vinifera", phase_id = 65, by = c("country", "year"), min_stations = 3, compute_trend = FALSE ) cat("Synchrony comparison (mean SD across years):\n") cat("Apple (flowering): ", round(sync$overall$mean_sd_doy, 1), "days\n") cat("Grapevine (flowering):", round(sync_vine$overall$mean_sd_doy, 1), "days\n") } else { cat("Insufficient grapevine data for synchrony comparison.\n") } ``` --- # Part 3: Combining Gradient and Synchrony Analysis A comprehensive spatial phenological analysis typically combines gradient and synchrony approaches. While each addresses a different aspect of spatial structure, together they provide a more complete picture of how phenology varies across landscapes. | Analysis | Question Answered | |----------|-------------------| | Gradient | How does MEAN phenological timing change across space? | | Synchrony | How VARIABLE is phenology within regions? | Gradients describe systematic spatial shifts (e.g. with elevation or latitude), whereas synchrony captures the degree of spatial coherence around these shifts. ```{r combined-analysis} # 1. Understand elevation gradient gradient <- pheno_gradient( pep, variable = "alt", species = "Malus domestica", phase_id = 60 ) cat("Elevation Gradient Analysis:\n") cat(" Slope:", round(gradient$summary$slope, 2), "days/100m\n") cat(" R-squared:", round(gradient$summary$r_squared, 3), "\n\n") # 2. Assess spatial synchrony synchrony <- pheno_synchrony( pep, species = "Malus domestica", phase_id = 60, min_stations = 3 ) cat("Synchrony Analysis:\n") cat(" Mean SD across stations:", round(synchrony$overall$mean_sd_doy, 1), "days\n") cat(" Mean CV:", round(synchrony$overall$mean_cv_pct, 1), "%\n") ``` The two analyses answer complementary questions: the gradient quantifies the direction and strength of spatial change, while synchrony indicates how tightly phenological timing aligns around that spatial pattern. ## Interpreting Combined Results Interpreting gradients and synchrony together helps to identify the dominant controls on phenology within a region: | Gradient | Synchrony | Interpretation | Example | |----------|-----------|----------------|---------| | Strong | High | Clear environmental control with uniform response | Continental climate regions | | Strong | Low | Environmental control with strong local variation | Mountain regions with microclimates | | Weak | High | Broad regional climate signal dominates| Coastal or maritime regions | | Weak | Low | Phenology shaped by complex local factors | Highly fragmented landscapes | This combined perspective is particularly useful for comparing regions, diagnosing model performance, and identifying where local processes may override large-scale climatic drivers. --- # Part 4: Mapping Phenological Patterns Spatial visualization is a critical component of phenological analysis. Before formal modeling, maps help to assess station coverage, identify spatial gaps, and explore geographic patterns in phenological timing. The `pep725` package provides two mapping functions: | Function | Type | Best suited for | |----------|------|----------| | `pheno_leaflet()` | Interactive | Data exploration and station selection | | `pheno_map()` | Static | Analysis summaries and publication-quality figures | ## Interactive Maps with pheno_leaflet() The `pheno_leaflet()` function launches an interactive Shiny-based map for exploring phenological station networks. It is particularly useful during the early stages of analysis for: - exploring spatial coverage and station density, - interactively selecting subsets of stations, - understanding geographic context before aggregation or modeling. ```{r leaflet-example, eval=FALSE} # Launch interactive map (opens in viewer) # Draw rectangles or polygons to select stations selected_stations <- pheno_leaflet(pep, label_col = "species") # The function returns a data.frame of selected stations print(selected_stations) ``` ```{r leaflet-screenshot, echo=FALSE, out.width="100%", fig.cap="The pheno_leaflet() interface showing station locations with drawing tools for selection."} # Display screenshot if it exists screenshot_path <- "pheno_leaflet_screenshot.png" if (file.exists(screenshot_path)) { knitr::include_graphics(screenshot_path) } else { # Placeholder message when screenshot doesn't exist cat("*[Screenshot: Interactive map showing PEP725 stations across Europe with drawing toolbar for rectangle and polygon selection]*\n") } ``` ### Features of pheno_leaflet() The interactive map supports multiple selection and inspection tools: | Feature | Purpose | |---------|------------| | **Click selection** | Select individual stations | | **Rectangle selection** | Select rectangular geographic areas using the rectangle tool from the toolbar | | **Polygon selection** | Define custom shapes to select irregular regions | | **Hover labels** | Move mouse over points to inspect station metadata | | **Done button** | Click "Done" to finalize and return selected stations | The function returns a `data.frame` containing all selected stations with their coordinates and metadata, which can then be directly reused in subsequent analysis. ### Best Practices for Interactive Mapping **Tip**: For large datasets, filtering before mapping substantially improves performance. ```{r leaflet-filtered, eval=FALSE} # Filter to a specific species for faster loading (recommended) apple <- pep[species == "Malus domestica"] selected <- pheno_leaflet(apple, label_col = "s_id") # Use selected stations for focused analysis apple_subset <- apple[s_id %in% selected$s_id] ``` **Why filter first?** The full PEP725 dataset contains millions of observations. Rendering all these points in an interactive map can take long. Restricting the dataset to a species or region of interest results in faster loading and smoother interaction. ## Static Maps with pheno_map() The `pheno_map()` function creates static maps suitable for reporting and publication. Two background options are supported: | `background` | Description | API Key Required? | |--------------|-------------|-------------------| | `"none"` | Country borders from Natural Earth | No | | `"google"` | Google Maps satellite/terrain imagery | Yes | For most applications, the `background = "none"` option is recommended because it: - requires no external services (API key setup), - works reliably in package vignettes, - produces reproducible, publication-ready maps ### Basic Station Maps ```{r map-basic, fig.height=6, fig.width=8} # Basic station map with country borders (no API key needed) pheno_map(pep, background = "none", color_by = "none", point_size = 1.5) ``` This view is useful for assessing overall network coverage and geographic gaps. ### Coloring by Data Attributes ```{r map-nobs, fig.height=6, fig.width=8} # Color stations by number of observations pheno_map(pep, background = "none", color_by = "n_obs", point_size = 1.5) ``` ```{r map-nspecies, fig.height=6, fig.width=8} # Color by species diversity at each station pheno_map(pep, background = "none", color_by = "n_species", point_size = 1.5) ``` ### Using Google Maps Background For satellite imagery (requires API key from Google Cloud Console): ```{r map-google, eval=FALSE} # Register your API key first ggmap::register_google(key = "your_api_key_here") # Then use background = "google" pheno_map(pep, background = "google", color_by = "n_obs", zoom = 5) # Regional focus with Google Maps pheno_map( pep, background = "google", location = c(lon = 8.2, lat = 46.8), zoom = 7, color_by = "n_obs" ) ``` These maps help identify well-monitored stations and multi-species observation sites. ## Mapping Phenological Patterns Beyond station metadata, `pheno_map()` can visualize derived phenological quantities, allowing spatial interpretation of biological signals. ### Mean Phenological Timing ```{r map-mean-doy, fig.height=6, fig.width=8} # Map mean phenological timing for flowering (phase 60) # Earlier timing = darker colors, later = lighter (plasma scale) pheno_map(pep, background = "none", color_by = "mean_doy", phase_id = 60, point_size = 1.5) ``` This representation reveals spatial gradients in average phenological timing. ### Phenological Trends ```{r map-trend, fig.height=6, fig.width=8} # Map trends per station # Blue = phenology getting earlier, Red = getting later pheno_map(pep, background = "none", color_by = "trend", phase_id = 60, period = 1990:2020, min_years = 10, point_size = 1.5) ``` Trend maps highlight regions where phenology is advancing or delaying over time. ### Species-level Variation ```{r map-species-cv, fig.height=6, fig.width=8} # Map species variation at each station # Higher CV = more variation in timing among species pheno_map(pep, background = "none", color_by = "species_cv", phase_id = 60, min_species = 3, point_size = 1.5) ``` High inter-species variability may indicate ecological heterogeneity or mixed habitat conditions. ### Understanding `color_by` Options | `color_by` | Meaning | Typical application | |------------|---------------|----------------| | `"none"` | Station locations | Observation network overview | | `"n_obs"` | Observation density | Identification of well-monitored stations | | `"n_species"` | Species richness | Finding multi-species stations | | `"mean_doy"` | Mean timing of day-of-year | Reveal spatial phenology gradients | | `"trend"` | Temporal change | Climate impact assessment | | `"species_cv"` | Inter-species variability | Find stations with consistent timing | ### Parameter Reference for pheno_map() | Parameter | Description | Default | |-----------|-------------|---------| | `background` | Map background: "none" or "google" | "google" | | `location` | Map center as c(lon, lat) | European center | | `zoom` | Zoom level (4=wide, 7=tight) | 4 | | `color_by` | Coloring option | "none" | | `phase_id` | BBCH phase for phenological colors | NULL | | `period` | Years for trend calculation | All years | | `min_years` | Minimum years for trend | 10 | | `min_species` | Minimum species for CV | 3 | | `point_size` | Marker size | 0.8 | | `output_file` | Path to save map | NULL (display only) | ## Combining Mapping with Analysis A typical workflow integrates mapping with spatial analysis: ```{r mapping-workflow, eval=FALSE} # 1. Explore stations interactively selected <- pheno_leaflet(pep[genus == "Malus"]) # 2. Subset data to selected region pep_region <- pep[s_id %in% selected$s_id] # 3. Analyze gradients in the selected region gradient <- pheno_gradient(pep_region, variable = "alt", species = "Malus domestica", phase_id = 60) # 4. Assess synchrony synchrony <- pheno_synchrony(pep_region, species = "Malus domestica", phase_id = 60) # 5. Create publication map of the region (no API needed) pheno_map(pep_region, background = "none", color_by = "mean_doy", phase_id = 60, output_file = "regional_phenology.pdf") ``` --- # Best Practices Summary ## For Gradient Analysis 1. **Check sample size**: Need sufficient stations across the gradient range (minimum 20 stations, ideally 50+) 2. **Use robust methods**: Phenological data often has outliers from observation errors or microclimate effects - always start with `method = "robust"` 3. **Consider regional differences**: Gradients may vary by location - use the `by` parameter to check consistency 4. **Validate against literature**: Compare your results to published lapse rates (2-4 days/100m for altitude is typical in temperate Europe) 5. **Report uncertainty**: Always include R-squared and sample size when reporting gradient estimates ## For Synchrony Analysis 1. **Set appropriate minimum stations**: Too few stations gives unreliable estimates (minimum 3, ideally 10+) 2. **Consider temporal scale**: Annual synchrony captures different patterns than decadal averages 3. **Account for network changes**: Station additions/removals can create artificial trends - check if network composition changed 4. **Use appropriate metrics**: SD for absolute variability, CV for relative comparisons across phases 5. **Interpret trends cautiously**: Distinguish statistically significant trends from ecologically meaningful changes ## For Mapping 1. **Start with exploration**: Use `pheno_leaflet()` to understand your data before formal analysis 2. **Choose appropriate zoom**: Match zoom level to your study area (4=Europe, 6=country, 8=region) 3. **Use meaningful colors**: Choose `color_by` option that matches your research question 4. **Document selections**: Save selected station lists for reproducibility 5. **Export for publication**: Use `output_file` to create high-quality figures --- ## Summary This vignette demonstrated how `pep725` supports spatial phenological analysis through complementary methods: | Topic | Key Function | Main Output | |-------|--------------|-------------| | Elevation gradients | `pheno_gradient()` | Days delay per 100m | | Latitude gradients | `pheno_gradient()` | Days delay per degree | | Spatial synchrony | `pheno_synchrony()` | SD/CV of timing across stations | | Interactive mapping | `pheno_leaflet()` | Selected station data.frame | | Static mapping | `pheno_map()` | Publication-quality maps | ### Key Take-Home Messages 1. **Phenology delays systematically** with increasing altitude and latitude - quantifying these gradients helps scale point observations to landscapes 2. **Synchrony tells you about spatial variability** - high synchrony suggests strong regional climate control, low synchrony indicates local factors matter 3. **Combine approaches** for complete understanding - gradients show mean patterns, synchrony shows variability around those patterns 4. **Mapping is essential** for exploring data, selecting regions, and communicating results ## Next Steps Explore the other vignettes for complementary analyses: - **Getting Started**: Data access, the `pep` class, and basic exploration ```{r eval = FALSE} vignette("getting-started", package = "pep725") ``` - **Phenological Analysis**: Normals, anomalies, quality assessment, and trends ```{r eval = FALSE} vignette("phenological-analysis", package = "pep725") ``` - **Data Quality Assessment**: Outlier detection and data validation ```{r eval = FALSE} vignette("data-quality", package = "pep725") ``` --- ## Session Info ```{r session} sessionInfo() ```