Install necessary packages and import appropriate data
pacman::p_load(tidyverse, readxl, raster, vegan, tigris, sf, sjPlot, sp, spOccupancy, ggrepel, lme4, lmerTest, MuMIn, brms, MCMCvis)
# Tree PCQ Data
tree_data <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/05_SharedData/Field_Data_FL_AL_MS.xlsx",
sheet = "Tree_PCQ")
# Soil Data
fuel_data <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/05_SharedData/Field_Data_FL_AL_MS.xlsx",
sheet = "Fuel_Sampling")
# Veg Data
Veg_Cover <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/05_SharedData/Field_Data_FL_AL_MS.xlsx",
sheet = "Veg_Cover")
# Shrub Cover Data
shrub_data <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/05_SharedData/Field_Data_FL_AL_MS.xlsx",
sheet = "Shrub_Cover")
# Site Data
CameraData <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/04_Wildlife/02_Data/CameraData.xlsx")
CameraLoc <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/04_Wildlife/02_Data/CameraLoc.xlsx",
sheet = "CameraLocations")
# Add effort data
effort_matrix <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/04_Wildlife/02_Data/CameraLoc.xlsx",
sheet = "Effort_Matrix_Full") %>%
pivot_longer(cols = matches("^202[4-5]-"), names_to = "week", values_to = "days") %>%
filter(days == "7") %>%
dplyr::select(Plot, week)
I moved this from a later section because the filtering process removed quadrats that did not capture any species. Rows labeled as “None” were removed, suggesting that the number of quadrats sampled per plot is not consistent across all plots.
# Count the total number of quadrats per plot
quadrat_count <- Veg_Cover %>%
group_by(Plot) %>%
summarize(total_quadrats = n_distinct(Quadrat), .groups = "drop")
#Filter tree data to only include trees with "tree" in the growth column
tree_data <- dplyr::filter(tree_data, Growth == "Tree")
#Filter Veg Cover to exclude Shrubs and Trees
Veg_Cover <- dplyr::filter(Veg_Cover, Growth != "Shrub" & Growth != "Tree")
#Filter Shrub Cover to only include Shrubs and Trees
shrub_data <- dplyr::filter(shrub_data, Growth == "Shrub" | Growth == "Tree")
# Calculate the total number of sites
total_sites <- nrow(CameraLoc)
# Function to filter data by frequency
filter_by_frequency <- function(df) {
# Group data by species and calculate the frequency
freq <- df %>%
group_by(Species) %>%
summarise(Frequency = n_distinct(Plot) / nrow(CameraLoc) * 100) %>%
filter(Frequency >= 3)
# Filter the original data to include only species with frequency >= 3%
filtered_df <- df %>%
filter(Species %in% freq$Species)
return(filtered_df)
}
# Filter tree data by frequency
tree_data <- filter_by_frequency(tree_data)
# Filter Veg Cover data by frequency
Veg_Cover <- filter_by_frequency(Veg_Cover)
# Filter Shrub Cover data by frequency
shrub_data <- filter_by_frequency(shrub_data)
# Total length of Shrub cover at a site
shrub_cover <- shrub_data %>%
mutate(Cover = Line_End - Line_Start) %>%
group_by(Species_Name, Plot) %>%
summarise(Shrub_Total_Cover = sum(Cover, na.rm = TRUE), .groups = "drop") %>%
mutate(Shrub_Percent_Cover = Shrub_Total_Cover / 3000 * 100)
# Summed length of shrub over at a site
shrub_cover_summed <- shrub_cover %>%
group_by(Plot) %>%
summarize(total_shrub_cover = sum(Shrub_Total_Cover, na.rm = TRUE), .groups = "drop")
# Combine Plot and Quadrat columns
Veg_Cover <- Veg_Cover %>%
mutate(Plot_Quadrat = paste(Plot, Quadrat, sep = '_'))
# Join with CogonSites to get site information
Veg_Cover <- Veg_Cover %>%
left_join(CameraLoc, by = "Plot")
# Sum species cover across quadrats for each species at each plot
veg_cover_summed <- Veg_Cover %>%
group_by(Plot, Species_Name) %>%
summarize(total_cover = sum(Cover_Per, na.rm = TRUE), .groups = "drop")
# Calculate average herbaceous species cover
avg_species_cover <- veg_cover_summed %>%
left_join(quadrat_count, by = "Plot") %>%
mutate(avg_cover = total_cover / total_quadrats)
This species matrix includes herbaceous and shrub species
# Merge shrub cover with herbaceous average cover
combined_cover <- avg_species_cover %>%
full_join(
shrub_cover %>%
dplyr::select(Plot, Species_Name, Shrub_Percent_Cover),
by = c("Plot", "Species_Name")
) %>%
mutate(
overlap_flag = ifelse(!is.na(avg_cover) & !is.na(Shrub_Percent_Cover), TRUE, FALSE), # Flag overlaps
final_cover = case_when(
!is.na(avg_cover) & is.na(Shrub_Percent_Cover) ~ avg_cover, # Use herbaceous cover if no shrub data
is.na(avg_cover) & !is.na(Shrub_Percent_Cover) ~ Shrub_Percent_Cover, # Use shrub cover if no herbaceous data
TRUE ~ NA_real_ # Leave as NA where overlaps exist
)
)
# Species Matrix
species_matrix <- combined_cover %>%
dplyr::select(Plot, Species_Name, final_cover) %>%
pivot_wider(
names_from = Species_Name,
values_from = final_cover,
values_fill = 0
)
avg_cogongrass_cover <- species_matrix %>%
group_by(Plot) %>%
summarize(Avg_Cogongrass_Cover = sum(Imperata_cylindrica, na.rm = TRUE) / n(), .groups = "drop")
# Summarize species cover by site
site_species_cover <- Veg_Cover %>%
group_by(Plot, Species_Name) %>%
summarize(total_cover = sum(Cover_Per, na.rm = TRUE)) %>%
ungroup()
## `summarise()` has grouped output by 'Plot'. You can override using the
## `.groups` argument.
# Calculate Shannon diversity per site
Veg_shannon_diversity <- site_species_cover %>%
group_by(Plot) %>%
mutate(proportion = total_cover / sum(total_cover)) %>%
summarize(Veg_shannon_index = -sum(proportion * log(proportion), na.rm = TRUE))
print(Veg_shannon_diversity)
## # A tibble: 206 × 2
## Plot Veg_shannon_index
## <chr> <dbl>
## 1 BI200 2.28
## 2 BI201 2.20
## 3 BI202 1.50
## 4 BI97 1.82
## 5 BI99 3.06
## 6 BN210 2.97
## 7 BN211 2.43
## 8 BN212 2.22
## 9 BN96 3.05
## 10 BN98 2.79
## # ℹ 196 more rows
if (!is.numeric(fuel_data$Height)) {
fuel_data$Height <- as.numeric(as.character(fuel_data$Height))
}
## Warning: NAs introduced by coercion
# Calculate average vegetation height per plot
veg_height <- fuel_data %>%
group_by(Plot) %>%
summarize(avg_veg_height = mean(Height, na.rm = TRUE), .groups = "drop")
# Tree density from point-centered quarter data
if (!is.numeric(tree_data$Distance)) {
tree_data$Distance <- as.numeric(as.character(tree_data$Distance))
}
tree_density_data <- tree_data %>%
group_by(Plot) %>%
summarize(Average_Distance = mean(Distance) / 100, # Convert to meters
Tree_Density = 10000 / (Average_Distance^2)) # Convert to trees per hectare
# Average canopy cover from vegetation quadrats
tree_canopy_data <- Veg_Cover %>%
distinct(Plot, Quadrat, .keep_all = TRUE) %>% # Ensure each quadrat counts once per plot
group_by(Plot) %>%
summarize(Avg_Canopy_Cover = mean(Canopy_Cover, na.rm = TRUE), .groups = "drop") # Calculate the average canopy cover per plot
cor(tree_density_data$Tree_Density, tree_canopy_data$Avg_Canopy_Cover)
## [1] 0.2742307
CameraLoc <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/04_Wildlife/02_Data/CameraLoc.xlsx",
sheet = "CameraLocations")
CameraData <- read_excel("C:/Users/DrewIvory/OneDrive - University of Florida/Desktop/School/PHD/01_Projects/04_Wildlife/02_Data/CameraData.xlsx")
avg_cogongrass_cover <- species_matrix %>%
group_by(Plot) %>%
summarize(Avg_Cogongrass_Cover = sum(Imperata_cylindrica, na.rm = TRUE) / n(), .groups = "drop")
CameraLoc <- CameraLoc %>%
left_join(avg_cogongrass_cover, by = "Plot")
# Observation per species, per site
site_species_counts <- CameraData %>%
group_by(Plot, Name) %>%
summarize(count = n(), .groups = "drop")
# Shannon Diversity per site
shannon_diversity_wildlife <- site_species_counts %>%
group_by(Plot) %>%
mutate(proportion = count / sum(count)) %>%
summarize(Wild_shannon_index = -sum(proportion * log(proportion), na.rm = TRUE))
# View results
print(shannon_diversity_wildlife)
## # A tibble: 32 × 2
## Plot Wild_shannon_index
## <chr> <dbl>
## 1 BI201 0.305
## 2 BN211 0.303
## 3 EI100 0.292
## 4 EI102 0.412
## 5 EI104 0.310
## 6 EI106 0.446
## 7 EN101 0.117
## 8 EN103 0.194
## 9 EN107 0.861
## 10 JI07 0.764
## # ℹ 22 more rows
# Merge wildlife and vegetation diversity indices with invasion data
diversity_data <- shannon_diversity_wildlife %>%
left_join(Veg_shannon_diversity, by = "Plot") %>%
left_join(CameraLoc, by = "Plot")
# View merged data
print(diversity_data)
## # A tibble: 32 × 15
## Plot Wild_shannon_index Veg_shannon_index Lat Long Status
## <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 BI201 0.305 2.20 30.8 -86.9 Invaded
## 2 BN211 0.303 2.43 30.8 -86.9 Non_Invaded
## 3 EI100 0.292 2.54 31.0 -87.1 Invaded
## 4 EI102 0.412 1.49 31.0 -87.1 Invaded
## 5 EI104 0.310 2.42 31.0 -87.1 Invaded
## 6 EI106 0.446 1.73 31.0 -87.1 Invaded
## 7 EN101 0.117 2.07 31.0 -87.1 Non_Invaded
## 8 EN103 0.194 2.43 31.0 -87.1 Non_Invaded
## 9 EN107 0.861 2.69 31.0 -87.1 Non_Invaded
## 10 JI07 0.764 1.69 30.8 -87.1 Invaded
## # ℹ 22 more rows
## # ℹ 9 more variables: Start_Date <dttm>, Camera <chr>, Cogon_Patch_Size <dbl>,
## # VegetationDiversity <dbl>, PostTreatmentDensities <dbl>, Authority <chr>,
## # Auth <dbl>, UTM_Zone <dbl>, Avg_Cogongrass_Cover <dbl>
summary(diversity_data)
## Plot Wild_shannon_index Veg_shannon_index Lat
## Length:32 Min. :0.04539 Min. :1.188 Min. :28.68
## Class :character 1st Qu.:0.29022 1st Qu.:2.024 1st Qu.:30.76
## Mode :character Median :0.44221 Median :2.369 Median :30.77
## Mean :0.56021 Mean :2.264 Mean :30.45
## 3rd Qu.:0.75653 3rd Qu.:2.522 3rd Qu.:30.90
## Max. :1.72721 Max. :3.160 Max. :31.01
## Long Status Start_Date
## Min. :-87.15 Length:32 Min. :2024-05-09 00:00:00
## 1st Qu.:-87.14 Class :character 1st Qu.:2024-06-03 18:00:00
## Median :-87.09 Mode :character Median :2024-06-06 12:00:00
## Mean :-86.21 Mean :2024-06-26 04:30:00
## 3rd Qu.:-86.89 3rd Qu.:2024-06-27 00:00:00
## Max. :-82.41 Max. :2024-11-04 00:00:00
## Camera Cogon_Patch_Size VegetationDiversity
## Length:32 Min. : 0.00 Min. :11.00
## Class :character 1st Qu.: 0.00 1st Qu.:18.00
## Mode :character Median : 30.07 Median :20.50
## Mean : 458.39 Mean :21.88
## 3rd Qu.: 233.84 3rd Qu.:25.00
## Max. :4168.92 Max. :42.00
## PostTreatmentDensities Authority Auth UTM_Zone
## Min. :0.0000 Length:32 Min. :1.000 Min. :16.00
## 1st Qu.:0.0000 Class :character 1st Qu.:2.000 1st Qu.:16.00
## Median :0.0000 Mode :character Median :3.000 Median :16.00
## Mean :0.8978 Mean :2.844 Mean :16.19
## 3rd Qu.:1.4650 3rd Qu.:3.000 3rd Qu.:16.00
## Max. :3.7100 Max. :4.000 Max. :17.00
## Avg_Cogongrass_Cover
## Min. : 0.000
## 1st Qu.: 0.000
## Median : 2.143
## Mean :13.683
## 3rd Qu.:20.089
## Max. :63.571
diversity_data <- diversity_data %>%
mutate(Status = as.factor(Status))
# Standardizing the continuous variables
diversity_data <- diversity_data %>%
mutate(
Avg_Cogongrass_Cover = scale(Avg_Cogongrass_Cover),
Veg_shannon_index = scale(Veg_shannon_index),
Cogon_Patch_Size = scale(Cogon_Patch_Size)
)
glmm_model <- lmer(
Wild_shannon_index ~ Avg_Cogongrass_Cover * Veg_shannon_index + Cogon_Patch_Size +
(1 | Authority) + (1 | Camera),
data = diversity_data
)
## boundary (singular) fit: see help('isSingular')
# Summarize the model
summary(glmm_model)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: Wild_shannon_index ~ Avg_Cogongrass_Cover * Veg_shannon_index +
## Cogon_Patch_Size + (1 | Authority) + (1 | Camera)
## Data: diversity_data
##
## REML criterion at convergence: 38.9
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.7385 -0.6306 -0.1460 0.4177 2.7655
##
## Random effects:
## Groups Name Variance Std.Dev.
## Authority (Intercept) 0.0000 0.0000
## Camera (Intercept) 0.0260 0.1613
## Residual 0.1279 0.3577
## Number of obs: 32, groups: Authority, 5; Camera, 4
##
## Fixed effects:
## Estimate Std. Error df t value
## (Intercept) 0.450256 0.121460 4.613877 3.707
## Avg_Cogongrass_Cover -0.166255 0.155059 26.891654 -1.072
## Veg_shannon_index 0.010820 0.108964 25.628316 0.099
## Cogon_Patch_Size -0.005934 0.078788 26.390634 -0.075
## Avg_Cogongrass_Cover:Veg_shannon_index -0.222671 0.080042 26.921474 -2.782
## Pr(>|t|)
## (Intercept) 0.01606 *
## Avg_Cogongrass_Cover 0.29316
## Veg_shannon_index 0.92168
## Cogon_Patch_Size 0.94053
## Avg_Cogongrass_Cover:Veg_shannon_index 0.00975 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) Av_C_C Vg_sh_ Cg_P_S
## Avg_Cgngr_C 0.269
## Vg_shnnn_nd -0.021 0.611
## Cgn_Ptch_Sz -0.148 -0.477 -0.058
## Avg_C_C:V__ 0.434 0.685 0.074 -0.403
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
# Extract the fixed effects
fixed_effects <- fixef(glmm_model)
# Extract the random effects
random_effects <- ranef(glmm_model)
# Plot the fixed effects
plot_model(glmm_model, type = "pred", terms = c("Avg_Cogongrass_Cover", "Veg_shannon_index"))
# Plot the random effects
plot_model(glmm_model, type = "re")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the sjPlot package.
## Please report the issue at <https://github.com/strengejacke/sjPlot/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## [[1]]
##
## [[2]]
bayesian_model <- brm(
Wild_shannon_index ~ scale(Avg_Cogongrass_Cover) * scale(Veg_shannon_index) + scale(Cogon_Patch_Size) +
(1 | Authority) + (1 | Camera),
data = diversity_data,
family = gaussian(),
chains = 3,
iter = 5000,
warmup = 3000,
cores = parallel::detectCores(),
control = list(adapt_delta = 0.99, max_treedepth = 15), # Further tuned parameters
prior = c(
prior(normal(0, 1), class = "b"), # Regularizing prior for coefficients
prior(normal(0, 1), class = "Intercept"), # Weakly informative cauchy prior for intercept
prior(normal(0, 1), class = "sd") # For random effect standard deviations
)
)
## Compiling Stan program...
## Start sampling
summary(bayesian_model)
## Family: gaussian
## Links: mu = identity
## Formula: Wild_shannon_index ~ scale(Avg_Cogongrass_Cover) * scale(Veg_shannon_index) + scale(Cogon_Patch_Size) + (1 | Authority) + (1 | Camera)
## Data: diversity_data (Number of observations: 32)
## Draws: 3 chains, each with iter = 5000; warmup = 3000; thin = 1;
## total post-warmup draws = 6000
##
## Multilevel Hyperparameters:
## ~Authority (Number of levels: 5)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept) 0.15 0.16 0.00 0.56 1.00 2745 2860
##
## ~Camera (Number of levels: 4)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept) 0.28 0.24 0.02 0.92 1.00 1709 2265
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI
## Intercept 0.41 0.22 -0.08
## scaleAvg_Cogongrass_Cover -0.14 0.18 -0.50
## scaleVeg_shannon_index 0.01 0.13 -0.24
## scaleCogon_Patch_Size -0.03 0.09 -0.21
## scaleAvg_Cogongrass_Cover:scaleVeg_shannon_index -0.21 0.09 -0.40
## u-95% CI Rhat Bulk_ESS
## Intercept 0.83 1.00 3020
## scaleAvg_Cogongrass_Cover 0.23 1.00 2548
## scaleVeg_shannon_index 0.27 1.00 4458
## scaleCogon_Patch_Size 0.15 1.00 3371
## scaleAvg_Cogongrass_Cover:scaleVeg_shannon_index -0.02 1.00 3202
## Tail_ESS
## Intercept 2386
## scaleAvg_Cogongrass_Cover 2838
## scaleVeg_shannon_index 3976
## scaleCogon_Patch_Size 3817
## scaleAvg_Cogongrass_Cover:scaleVeg_shannon_index 3456
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 0.38 0.06 0.29 0.52 1.00 4397 4078
##
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
plot(bayesian_model)
# Plot the fixed effects
plot(bayesian_model, "Avg_Cogongrass_Cover")
## Warning: Argument 'pars' is deprecated. Please use 'variable' instead.
# Plot the random effects
plot(bayesian_model, "Camera")
## Warning: Argument 'pars' is deprecated. Please use 'variable' instead.
plot(bayesian_model, "Authority")
## Warning: Argument 'pars' is deprecated. Please use 'variable' instead.
# Get unique levels of Authority and Camera from original data
authority_levels <- levels(as.factor(diversity_data$Authority))
camera_levels <- levels(as.factor(diversity_data$Camera))
# Create a new data frame for predictions
new_data <- expand.grid(
Avg_Cogongrass_Cover = seq(min(diversity_data$Avg_Cogongrass_Cover), max(diversity_data$Avg_Cogongrass_Cover), length.out = 100),
Veg_shannon_index = quantile(diversity_data$Veg_shannon_index, probs = c(0.25, 0.5, 0.75)),
Cogon_Patch_Size = mean(diversity_data$Cogon_Patch_Size), # Use mean value for this predictor
Authority = authority_levels[1], # Assign a representative level for Authority
Camera = camera_levels[1] # Assign a representative level for Camera
)
# Repeat new_data to match for each combination of Camera levels
new_data <- as.data.frame(new_data)
new_data <- new_data[rep(seq_len(nrow(new_data)), each = length(authority_levels) * length(camera_levels)), ]
new_data$Authority <- rep(authority_levels, each = 100 * length(camera_levels))
new_data$Camera <- rep(camera_levels, times = 100 * length(authority_levels))
# Generate predictions including random effects
predictions <- fitted(bayesian_model, newdata = new_data, re_formula = NULL)
new_data$Wild_shannon_index <- rowMeans(predictions)
ggplot(new_data, aes(x = Avg_Cogongrass_Cover, y = Wild_shannon_index, color = factor(Veg_shannon_index))) +
geom_line() +
labs(x = "Average Cogongrass Cover", y = "Wild Shannon Index", color = "Vegetation Shannon Index") +
theme_minimal() +
ggtitle("Effect of Cogongrass Cover and Veg. Shannon Index on Wild Shannon Index")