Set working directory

setwd("/EEB 4100/Final Project") #set a working directory

Load all necessary libraries

#Load possible packages
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.3.3
## Warning: package 'ggplot2' was built under R version 4.3.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.0     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(skimr)
library(sf)
## Warning: package 'sf' was built under R version 4.3.3
## Linking to GEOS 3.11.2, GDAL 3.8.2, PROJ 9.3.1; sf_use_s2() is TRUE
library(leaflet)
## Warning: package 'leaflet' was built under R version 4.3.3
library(scales)
## 
## Attaching package: 'scales'
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
library(ggmap)
## ℹ Google's Terms of Service: <https://mapsplatform.google.com>
##   Stadia Maps' Terms of Service: <https://stadiamaps.com/terms-of-service/>
##   OpenStreetMap's Tile Usage Policy: <https://operations.osmfoundation.org/policies/tiles/>
## ℹ Please cite ggmap if you use it! Use `citation("ggmap")` for details.
library(readxl)
## Warning: package 'readxl' was built under R version 4.3.3
library(raster)
## Loading required package: sp
## 
## Attaching package: 'raster'
## 
## The following object is masked from 'package:skimr':
## 
##     bind
## 
## The following object is masked from 'package:dplyr':
## 
##     select

View the dataset

#Dataset into R
ss_obsv <- read_excel("Song_Sparrow_Obsv.xlsx")
print(ss_obsv)    # View the dataset
## # A tibble: 20 × 21
##    `Species Name` `Scientific Name` State Location          Coordinates Latitude
##    <chr>          <chr>             <chr> <chr>             <chr>          <dbl>
##  1 Song Sparrow   Melospiza melodia CT    33 Nancy Drive, … 41.418697,…     41.4
##  2 Song Sparrow   Melospiza melodia CT    Quarry Road, New… 41.278177,…     41.3
##  3 Song Sparrow   Melospiza melodia CT    Tarrywile Park, … 41.3754293…     41.4
##  4 Song Sparrow   Melospiza melodia CT    Hartford          41.7849541…     41.8
##  5 Song Sparrow   Melospiza melodia CT    Pistol Creek Par… 41.5989289…     41.6
##  6 Song Sparrow   Melospiza melodia CT    Roaring Brook Na… 41.8412831…     41.8
##  7 Song Sparrow   Melospiza melodia CT    Milford Point, C… 41.1754303…     41.2
##  8 Song Sparrow   Melospiza melodia CT    Tulmeadow Farm, … 41.8726165…     41.9
##  9 Song Sparrow   Melospiza melodia CT    Quarry Road, New… 41.278177,…     41.3
## 10 Song Sparrow   Melospiza melodia CT    Westmoor Park, H… 41.7836289…     41.8
## 11 Song Sparrow   Melospiza melodia AZ    Riparian Preserv… 33.3614502…     33.4
## 12 Song Sparrow   Melospiza melodia AZ    Sweetwater Wetla… 32.278549,…     32.3
## 13 Song Sparrow   Melospiza melodia AZ    Glendale Recharg… 33.5242237…     33.5
## 14 Song Sparrow   Melospiza melodia AZ    Gilbert and Chan… 33.2386696…     33.2
## 15 Song Sparrow   Melospiza melodia AZ    Riparian Preserv… 33.3614502…     33.4
## 16 Song Sparrow   Melospiza melodia AZ    stakeout Golden-… 33.517422,…     33.5
## 17 Song Sparrow   Melospiza melodia AZ    Sweetwater Wetla… 32.278549,…     32.3
## 18 Song Sparrow   Melospiza melodia AZ    Hassayampa River… 33.9333419…     33.9
## 19 Song Sparrow   Melospiza melodia AZ    Canoa Ranch Cons… 31.7948045…     31.8
## 20 Song Sparrow   Melospiza melodia AZ    Tres Rios Overba… 33.389402,…     33.4
## # ℹ 15 more variables: Longitude <dbl>, Date <dttm>,
## #   `eBird Checklist ID` <chr>, `Macaulay Library Catalog ID` <chr>,
## #   `Macaulay Library Page` <chr>, Photographer <chr>, `Age of Bird` <chr>,
## #   `Original Photo` <chr>, `Selected Area` <chr>, `Average Color` <lgl>,
## #   RGB <chr>, Hexadecimal <chr>, HSL <chr>, Lightness <dbl>,
## #   `Color Finder` <chr>
str(ss_obsv)     # Examine the structure of the data
## tibble [20 × 21] (S3: tbl_df/tbl/data.frame)
##  $ Species Name               : chr [1:20] "Song Sparrow" "Song Sparrow" "Song Sparrow" "Song Sparrow" ...
##  $ Scientific Name            : chr [1:20] "Melospiza melodia" "Melospiza melodia" "Melospiza melodia" "Melospiza melodia" ...
##  $ State                      : chr [1:20] "CT" "CT" "CT" "CT" ...
##  $ Location                   : chr [1:20] "33 Nancy Drive, Fairfield" "Quarry Road, New Haven" "Tarrywile Park, Fairfield" "Hartford" ...
##  $ Coordinates                : chr [1:20] "41.418697, -73.442016" "41.278177, -72.742086" "41.3754293, -73.4535956" "41.7849541, -72.7109299" ...
##  $ Latitude                   : num [1:20] 41.4 41.3 41.4 41.8 41.6 ...
##  $ Longitude                  : num [1:20] -73.4 -72.7 -73.5 -72.7 -72.7 ...
##  $ Date                       : POSIXct[1:20], format: "2023-11-22" "2023-12-26" ...
##  $ eBird Checklist ID         : chr [1:20] "S155003917" "S157150385" "S127679025" "S134921546" ...
##  $ Macaulay Library Catalog ID: chr [1:20] "ML611450322" "ML612689641" "ML576007381" "ML562451521" ...
##  $ Macaulay Library Page      : chr [1:20] "https://macaulaylibrary.org/asset/611450322" "https://macaulaylibrary.org/asset/612689641" "https://macaulaylibrary.org/asset/576007381" "https://macaulaylibrary.org/asset/562451521" ...
##  $ Photographer               : chr [1:20] "Alton Spencer" "Caleb Villar" "Alton Spencer" "Debbie Lombardo" ...
##  $ Age of Bird                : chr [1:20] "Adult" "Adult" "Adult" "Adult" ...
##  $ Original Photo             : chr [1:20] "ML611450322" "ML612689641" "ML576007381" "ML562451521" ...
##  $ Selected Area              : chr [1:20] "ML611450322_Selected" "ML612689641_Selected" "ML576007381_Selected" "ML562451521_Selected" ...
##  $ Average Color              : logi [1:20] NA NA NA NA NA NA ...
##  $ RGB                        : chr [1:20] "61, 56, 51" "59, 54, 50" "88, 77, 69" "80, 78, 71" ...
##  $ Hexadecimal                : chr [1:20] "#3d3833" "#3b3632" "#584d45" "#504e47" ...
##  $ HSL                        : chr [1:20] "30, 9%, 22%" "27, 8%, 21%" "25, 12%, 31%" "47, 6%, 30%" ...
##  $ Lightness                  : num [1:20] 0.22 0.21 0.31 0.3 0.16 0.27 0.14 0.31 0.16 0.16 ...
##  $ Color Finder               : chr [1:20] "Dune" "Dune" "Liver" "Liiver" ...
summary(ss_obsv) # Summarize the data
##  Species Name       Scientific Name       State             Location        
##  Length:20          Length:20          Length:20          Length:20         
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  Coordinates           Latitude       Longitude      
##  Length:20          Min.   :31.79   Min.   :-112.69  
##  Class :character   1st Qu.:33.36   1st Qu.:-111.73  
##  Mode  :character   Median :37.55   Median : -92.23  
##                     Mean   :37.30   Mean   : -92.33  
##                     3rd Qu.:41.46   3rd Qu.: -72.83  
##                     Max.   :41.87   Max.   : -72.71  
##       Date                     eBird Checklist ID Macaulay Library Catalog ID
##  Min.   :2023-01-14 00:00:00   Length:20          Length:20                  
##  1st Qu.:2023-04-13 06:00:00   Class :character   Class :character           
##  Median :2023-09-25 00:00:00   Mode  :character   Mode  :character           
##  Mean   :2023-08-10 21:36:00                                                 
##  3rd Qu.:2023-11-24 18:00:00                                                 
##  Max.   :2023-12-26 00:00:00                                                 
##  Macaulay Library Page Photographer       Age of Bird        Original Photo    
##  Length:20             Length:20          Length:20          Length:20         
##  Class :character      Class :character   Class :character   Class :character  
##  Mode  :character      Mode  :character   Mode  :character   Mode  :character  
##                                                                                
##                                                                                
##                                                                                
##  Selected Area      Average Color      RGB            Hexadecimal       
##  Length:20          Mode:logical   Length:20          Length:20         
##  Class :character   NA's:20        Class :character   Class :character  
##  Mode  :character                  Mode  :character   Mode  :character  
##                                                                         
##                                                                         
##                                                                         
##      HSL              Lightness      Color Finder      
##  Length:20          Min.   :0.1400   Length:20         
##  Class :character   1st Qu.:0.2175   Class :character  
##  Mode  :character   Median :0.3000   Mode  :character  
##                     Mean   :0.2820                     
##                     3rd Qu.:0.3400                     
##                     Max.   :0.4500
#Includes range in lightness values

Variables to be used in maps

#Categorizing the lightness values for plummage color from the data set
Black <- ss_obsv %>% 
  filter(Lightness >= 0.00, Lightness <= 0.20) #filter for lightness values within said range

DarkGray <- ss_obsv %>% 
  filter(Lightness >= 0.21, Lightness <= 0.40)

Gray <- ss_obsv %>% 
  filter(Lightness >= 0.41, Lightness <= 0.60)

LightGray <- ss_obsv %>%
  filter(Lightness >= 0.61, Lightness <= 0.80)

White <- ss_obsv %>%
  filter(Lightness >= 0.81, Lightness <= 1.0)

#Filter dataset by region
ssparrow_CT <- ss_obsv %>% #filter by state
  filter(State=="CT")

ssparrow_AZ <- ss_obsv %>% 
  filter(State=="AZ")

#Circle the states using their coordinates
arizona_center <- c(mean(c(-114.818, -109.045)), mean(c(32.541, 37)))
connecticut_center <- c(mean(c(-73.727775, -71.787115)), mean(c(41.022732, 42.050002)))

Histogram of lightness observations

#created a subset of the original data frames to be used to make a histogram of the observations
histo_data <- rbind(
  data.frame(State = "CT", Lightness = ssparrow_CT$Lightness),
  data.frame(State = "AZ", Lightness = ssparrow_AZ$Lightness)
)

lightness_groups <- c("Black", "DarkGray", "Gray", "LightGray", "White") #Categorize the groups

# Create a function to classify lightness values into groups (5 categories, values range from 0-1.0)
classify_lightness <- function(lightness) {
  cut(lightness, breaks = c(0, 0.20, 0.40, 0.60, 0.80, 1.0), labels = lightness_groups, include.lowest = TRUE)
}

# Add the lightness groups to the histo_data variable
histo_data$Lightness_Group <- classify_lightness(histo_data$Lightness)

#Stacked Histogram of Plummage Lightness Observations (x-axis = State, Y-axis = Number of Observations, Fill = Lightness Group)
ggplot(histo_data, aes(x = State)) +
geom_bar(aes(fill = Lightness_Group)) + labs(title = "Observations of Plummage Lightness", x = "State", y = "Number of Observations", fill = "Plummage Lightness") + scale_fill_manual(values = c("Black" = "black", "DarkGray" = "darkgray", "Gray" = "gray"), labels = c("Black (0-20%)", "Dark Gray (21-40%)", "Gray (41-60%)")) + #Labels include lightness range
  theme_bw() +
  theme(  
    panel.grid.major.y = element_blank(),  #Removed horizontal grid lines
    panel.grid.minor.y = element_blank(),  #Removed horizontal grid lines
    panel.border = element_blank(),  # Remove borders
    axis.line = element_line(color = "black", size = 0.5),  # Added darker axis lines
    axis.title = element_text(size = 14),  #Font Size
    axis.text = element_text(size = 10),  #Font Size
    axis.ticks = element_line(color = "black")) 
## Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Location Map

location_map <- leaflet() %>% #Using leaflet to build the map and ESRI National Geographic World Map for the base map
  setView(lng = -79, lat = 37.8, zoom = 5) %>% 
  addTiles() %>%
  addProviderTiles(providers$Esri.NatGeoWorldMap) %>%

#Add circles around the areas of interest (Arizona and Connecticut). Changed the radius to highlight the whole states.
  addCircles(
    lng = arizona_center[1], lat = arizona_center[2], #Uses the center of the states defined above
    fillColor = "NA",
    radius = 400000,  
    color = "#FEFE62",  
    weight = 5       
  ) %>%
  addCircles(
    lng = connecticut_center[1], lat = connecticut_center[2],
    fillColor = "NA",
    radius = 80500, 
    color = "#FEFE62", 
    weight = 5
  ) %>%
  
  #Lightness color Observations: Circle markers used for each observation
  addCircleMarkers(data = Black, color = "black", fillOpacity = 1, radius = 5, group = "Black: 0-20% Lightness") %>%
  addCircleMarkers(data = DarkGray, color = "black", fillColor = "gray", fillOpacity = 1, radius = 5, group = "Dark Gray: 21-40% Lightness") %>% #All outlines done in black to make them more noticable/
  addCircleMarkers(data = Gray, color = "black", fillColor = "darkgray", fillOpacity = 1, radius = 5, group = "Gray: 41-60% Lightness") %>% #Darkgray and gray colors were switched for fill color because on the map, gray appeared darker than darkgray.
  addCircleMarkers(data = LightGray, color = "black", fillColor = "lightgray", fillOpacity = 1, radius = 5, group = "Light Gray: 61-80% Lightness") %>%
  addCircleMarkers(data = White, color = "black", fillColor = "white", fillOpacity = 1, radius = 5, group = "White: 81-100% Lightness") %>%
  
  #Added Layers Control to be able to look at the number of specific observation in each lightness value
  addLayersControl(
    overlayGroups = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness", "Light Gray: 61-80% Lightness", "White: 81-100% Lightness"),
    options = layersControlOptions(collapsed = FALSE)) %>%
 
  #Legend of all the lightness categories along with how they are classified
  addLegend(position = "bottomright", title = "Legend",
            colors = c("black", "gray", "darkgray", "lightgray", "white"), 
            labels = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness", "Light Gray: 61-80% Lightness", "White: 81-100% Lightness"), 
            opacity = 1)
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
location_map

Average Annual Precipitation Raster for US

#Precipitation Raster from WorldClim (Prec)
precip_data <- getData("worldclim", var = "prec", res = 10)
## Warning in getData("worldclim", var = "prec", res = 10): getData will be removed in a future version of raster
## . Please use the geodata package instead
#Clipped the raster to just represent the US (Lower 48 states)
US_border <- extent(-125, -66.5, 24, 49.5) 
USprecip_data <- crop(precip_data, US_border)

#Originally showed average temperatures for each month. Found the mean of all the data to get the yearly average 
avg_precip <- mean(USprecip_data)

#Precipitation color scale (red = low precipitation, darkblue = high precipitation)
color_precip <- colorNumeric(
  palette  = c("red", "yellow", "green", "blue", "darkblue"),
  domain = c(0, 250) #ranges from 0-250 mm of precipitation
)

Precipitation Map

precipitation_map <- leaflet() %>% 
  setView(lng = -79, lat = 37.8, zoom = 5) %>% 
  addTiles() %>%
  addProviderTiles(providers$Esri.NatGeoWorldMap) %>% #Same as observation map
  
  #Lightness Plummage Observations. Same as the observations map, but removed lightgray and white since there were no observations within those ranges
  addCircleMarkers(data = Black, color = "black", fillOpacity = 1, radius = 5, group = "Black: 0-20% Lightness") %>%
  addCircleMarkers(data = DarkGray, color = "black", fillColor = "gray", fillOpacity = 1, radius = 5, group = "Dark Gray: 21-40% Lightness") %>%
  addCircleMarkers(data = Gray, color = "black", fillColor = "darkgray", fillOpacity = 1, radius = 5, group = "Gray: 41-60% Lightness") %>%

  
  #Added the average precipitation raster and used the color_precip palette to represent it on the map
  addRasterImage(avg_precip, colors = color_precip, opacity = 0.4, group = "Precipitation (mm)") %>%
  
  #Added Layers Control to be able to look at the number of specific observation in each lightness value and to remove/add precipitation
   addLayersControl(
    overlayGroups = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness", "Precipitation (mm)"),
    options = layersControlOptions(collapsed = FALSE)) %>%
  
  #Added a legend for the observations
  addLegend(position = "bottomright", title = "Legend",
            colors = c("black", "gray", "darkgray"), 
            labels = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness"), 
            opacity = 1) %>%
  
  #Added a legend for the precipitation colors so viewers are aware of what the colors mean
   addLegend(position = "bottomright", title = "Average Annual Precipitation (mm)",
            colors = color_precip(seq(0, 250, by = 50)),
            labels = seq(0, 250, by = 50),
            opacity = .5)
## Warning in colors(.): Some values were outside the color scale and will be
## treated as NA
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
precipitation_map

Average Annual Temperature Raster for US

#Temperature Raster from WorldClim (using tmean (mean temperatures))
temp_data <- getData("worldclim", var = "tmean", res = 10)
## Warning in getData("worldclim", var = "tmean", res = 10): getData will be removed in a future version of raster
## . Please use the geodata package instead
UStemp_data <- crop(temp_data, US_border) #cropped the raster to just show the US

avg_temp_large <- mean(UStemp_data) #Found the yearly average

avg_temp <- avg_temp_large / 10 #Originally units were °C x 10, so I divided the values by 10 to just have the temperature in °C

#Temperature color scale (lightblue = colder, red = warmer)
color_temp <- colorNumeric(
  palette = c("lightblue", "blue", "green", "yellow", "red"), 
  domain = c(0, 25) 
)

#Temperature Map

temp_map <- leaflet() %>% 
  setView(lng = -79, lat = 37.8, zoom = 5) %>% 
  addTiles() %>%
  addProviderTiles(providers$Esri.NatGeoWorldMap) %>% #Same basemap as other maps
  
  #Lightness Plummage Observations. Same as the observations map, but removed lightgray and white since there were no observations within those ranges
   addCircleMarkers(data = Black, color = "black", fillOpacity = 1, radius = 5, group = "Black: 0-20% Lightness") %>%
  addCircleMarkers(data = DarkGray, color = "black", fillColor = "gray", fillOpacity = 1, radius = 5, group = "Dark Gray: 21-40% Lightness") %>%
  addCircleMarkers(data = Gray, color = "black", fillColor = "darkgray", fillOpacity = 1, radius = 5, group = "Gray: 41-60% Lightness") %>%
  
  #Added the average annual temperature raster and used the color_temp palette to represent it on the map
  addRasterImage(avg_temp, colors = color_temp, opacity = 0.5, group = "Temperature (°C)") %>%
  
  #Layer controls to be able to look at the number of specific observation in each lightness value and to remove/add temperature
   addLayersControl(
    overlayGroups = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness", "Temperature (°C)"),
    options = layersControlOptions(collapsed = FALSE)) %>%
  
  #Added a legend for the observations
  addLegend(position = "bottomright", title = "Legend",
            colors = c("black", "gray", "darkgray"), 
            labels = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness"), 
            opacity = 1) %>%
  
  #Added a legend for the precipitation colors so viewers are aware of what the colors mean (range from 0-25°C)
    addLegend(position = "bottomright", title = "Average Annual Temperature (°C)",
            colors = color_temp(seq(0, 25, by = 5)),
            labels = seq(0, 25, by = 5),
            opacity = .5)
## Warning in colors(.): Some values were outside the color scale and will be
## treated as NA
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
temp_map

Altitude Raster for US

#Altitude Raster from WorldClim using altitude (alt) variable
altitude_data <- getData("worldclim", var = "alt", res = 10)
## Warning in getData("worldclim", var = "alt", res = 10): getData will be removed in a future version of raster
## . Please use the geodata package instead
USalt <- crop(altitude_data, US_border) #Clipped to US

#Did not need to find the average due to altitude not changing from month to month


#Altitude color scale (lightblue = low altitude, red = high altitude)
color_alt <- colorNumeric(
  palette = c("lightblue", "blue", "green", "yellow", "red"), 
  domain = c(0, 3500) 
)

Altitude Map

altitude_map <- leaflet() %>% 
  setView(lng = -79, lat = 37.8, zoom = 5) %>% 
  addTiles() %>%
  addProviderTiles(providers$Esri.NatGeoWorldMap) %>% #Same as other maps
  
  #Lightness Plummage Observations. Same as the observations map, but removed lightgray and white since there were no observations within those ranges
   addCircleMarkers(data = Black, color = "black", fillOpacity = 1, radius = 5, group = "Black: 0-20% Lightness") %>%
  addCircleMarkers(data = DarkGray, color = "black", fillColor = "gray", fillOpacity = 1, radius = 5, group = "Dark Gray: 21-40% Lightness") %>%
  addCircleMarkers(data = Gray, color = "black", fillColor = "darkgray", fillOpacity = 1, radius = 5, group = "Gray: 41-60% Lightness") %>%
  
  #Added the altitude raster and used the color_alt palette to represent it on the map
  addRasterImage(USalt, colors = color_alt, opacity = 0.5, group = "Altitude") %>%
  
  #Layer controls to be able to look at the number of specific observation in each lightness value and to remove/add altitude
   addLayersControl(
    overlayGroups = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness", "Altitude (m)"),
    options = layersControlOptions(collapsed = FALSE)) %>%
  
 #Added a legend for the observations
  addLegend(position = "bottomright", title = "Legend",
            colors = c("black", "gray", "darkgray"), 
            labels = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness"), 
            opacity = 1) %>%
  
  #Added a legend for the altitude colors so viewers are aware of what the colors represent (range from 0-3500m)
    addLegend(position = "bottomright", title = "Altitude (m)",
            colors = color_alt(seq(0, 3500, by = 500)),
            labels = seq(0, 3500, by = 500),
            opacity = 0.5)
## Warning in colors(.): Some values were outside the color scale and will be
## treated as NA
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
altitude_map

Map including temperature, precipitation, and altitude rasters

Final_Map <- leaflet() %>% 
  setView(lng = -79, lat = 37.8, zoom = 5) %>% 
  addTiles() %>%
  addProviderTiles(providers$Esri.NatGeoWorldMap) %>% #Same basemap as other maps
  
  #Observations (same as the above maps)
   addCircleMarkers(data = Black, color = "black", fillOpacity = 1, radius = 5, group = "Black: 0-20% Lightness") %>%
  addCircleMarkers(data = DarkGray, color = "black", fillColor = "gray", fillOpacity = 1, radius = 5, group = "Dark Gray: 21-40% Lightness") %>%
  addCircleMarkers(data = Gray, color = "black", fillColor = "darkgray", fillOpacity = 1, radius = 5, group = "Gray: 41-60% Lightness") %>%

  
  #Added each of the climate rasters and their corresponding color palettes
  addRasterImage(avg_precip, colors = color_precip, opacity = 0.4, group = "Precipitation (mm)") %>%
  addRasterImage(avg_temp, colors = color_temp, opacity = 0.5, group = "Temperature (°C)") %>%
  addRasterImage(USalt, colors = color_alt, opacity = 0.5, group = "Altitude (m)") %>%
  
  #Only Included the climate variables to the layers control so viewer can directly see relationships between the 3 in the areas of interest
  addLayersControl(
    overlayGroups = c("Precipitation (mm)", "Temperature (°C)", "Altitude (m)"),
    options = layersControlOptions(collapsed = FALSE)) %>%
  
  #Due to space constraints, only black, dark gray, and gray were included in the legend since there were no observations for light gray or white.
  addLegend(position = "topright", title = "Legend",
            colors = c("black", "gray", "darkgray"), 
            labels = c("Black: 0-20% Lightness", "Dark Gray: 21-40% Lightness", "Gray: 41-60% Lightness"), 
            opacity = 1) %>%
  
  #Legend for Precipitation raster
  addLegend(position = "bottomleft", title = "Average Annual Precipitation (mm)",
            colors = color_precip(seq(0, 250, by = 50)),
            labels = seq(0, 250, by = 50),
            opacity = .5) %>%
  
  #Legend for Temperature raster
  addLegend(position = "bottomleft", title = "Average Annual Temperature (°C)",
            colors = color_temp(seq(0, 25, by = 5)),
            labels = seq(0, 25, by = 5),
            opacity = .5) %>%
  
  #Legend for Altitude raster
  addLegend(position = "bottomright", title = "Altitude (m)",
            colors = color_alt(seq(0, 3500, by = 500)),
            labels = seq(0, 3500, by = 500),
            opacity = 0.5)
## Warning in colors(.): Some values were outside the color scale and will be
## treated as NA
## Warning in colors(.): Some values were outside the color scale and will be
## treated as NA
## Warning in colors(.): Some values were outside the color scale and will be
## treated as NA
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively
Final_Map