# co2_community_roots
co2_community_root_cores <- read_csv("../1999 CO2xCommunity Root Biomass Data Assembled.csv",
na = c("", "NA", -99))
## Parsed with column specification:
## cols(
## community = col_character(),
## plot = col_double(),
## treatment = col_character(),
## core = col_double(),
## depth_center = col_double(),
## target_width = col_double(),
## volume = col_double(),
## washer = col_character(),
## plucker = col_character(),
## category = col_character(),
## mass = col_double(),
## seeds = col_double()
## )
First, I'm making sure that there are no redundant entries. This was an issue with an earlier version. I used R
(R Core Team 2019) and tidyverse
(Wickham 2017) packages for curation and graphing.
# First curate the CO2 x Community Data
co2_by_community_n <- co2_community_root_cores %>%
# Group by community, plot, treamtement, core, depth increment, and category
group_by(community, plot, treatment, category, core, depth_center) %>%
# Get the mean biomass
summarise(n = n()) %>%
arrange(n)
head(co2_by_community_n)
## # A tibble: 6 x 7
## # Groups: community, plot, treatment, category, core [1]
## community plot treatment category core depth_center n
## <chr> <dbl> <chr> <chr> <dbl> <dbl> <int>
## 1 SC 1 E DRT 1 2.5 1
## 2 SC 1 E DRT 1 5 1
## 3 SC 1 E DRT 1 7.5 1
## 4 SC 1 E DRT 1 10 1
## 5 SC 1 E DRT 1 12.5 1
## 6 SC 1 E DRT 1 15 1
tail(co2_by_community_n)
## # A tibble: 6 x 7
## # Groups: community, plot, treatment, category, core [1]
## community plot treatment category core depth_center n
## <chr> <dbl> <chr> <chr> <dbl> <dbl> <int>
## 1 SP 14 E WRH 2 15 1
## 2 SP 14 E WRH 2 21.2 1
## 3 SP 14 E WRH 2 32.5 1
## 4 SP 14 E WRH 2 52.5 1
## 5 SP 14 E WRH 2 72.5 1
## 6 SP 14 E WRH 2 92.5 1
Then I did some quick renaming, rearranging of variables and filtering.
co2_by_community <- co2_community_root_cores %>%
# create top and bottom depth increments
mutate(top = depth_center - (target_width)/2,
bottom = depth_center + (target_width)/2) %>%
# Filter out litter and seeds
filter(! category %in% c("LITT", "SCseeds")) %>%
ungroup() %>%
# Rename abbreviated samples to make the more readable
mutate(category = recode(category,
"LRT"="light-colored roots",
"RRT"="red roots",
"DRT"="dark roots",
"WRH"="white rhizome",
"RRH"="red rhizome",
"RHC"="rhizomotous culms",
"NRHC"="non-rhizomotous culms"),
community = recode(community, "SC"= "Schoenoplectus americanus",
"SP"="Spartina patens"),
treatment = recode(treatment, "E"="Elevated",
"A" = "Ambient")
)
biomass_com_core_cat <- ggplot(data = co2_by_community,
aes(x = bottom,
y = mass,
color = category)) +
geom_point(alpha=0.66) +
geom_line(aes(group = paste(community, plot, treatment, category, core, sep="-")),
lty = 2,
alpha=0.66) +
facet_wrap(community~treatment) +
xlab("Depth (cm)") +
ylab("Biomass (g)") +
scale_x_reverse() +
coord_flip() +
theme(legend.position = "right",
legend.title = element_blank()) +
guides(col = guide_legend(ncol = 1))
(biomass_com_core_cat)
The measurements for each core are not all continuous. Near the top of the core measurements are continuous and 2.5 cm wide, but deeper, they are discontinous, 5 cm wide, representing wider depth increments. For biomass measurements, I scaled weights by the ratio of their measured width to their representative width. For each core, I calculated the cumulative sum of biomass for each depth increment, and normalized it by the total sum of biomass. I then rescaled this normalized biomass to equal 0.999, or 99.9% of the total biomass. I am assuming that the shape of the root zone is exponential, and that the core captures nearly 100% (%99.9) of the total live roots of the plants.
co2_by_community_scaled <- co2_by_community %>%
group_by(community, plot, core, treatment, depth_center, target_width, top, bottom, volume) %>%
summarise(total_mass = sum(mass)) %>%
ungroup() %>%
group_by(community, plot, core, treatment) %>%
mutate(increment_n = 1:n()) %>%
mutate(representative_top = ifelse(increment_n == 1,
0,
(lag(bottom)-top)/2+top),
representative_bottom = ifelse(increment_n == max(increment_n),
max(bottom),
(bottom-lead(top))/2+lead(top)),
representative_volume = (representative_bottom-representative_top)*(5.1/2)^2*pi) %>%
ungroup() %>%
mutate(scale_factor = representative_volume/volume,
scaled_mass = total_mass * scale_factor) %>%
group_by(community, plot, core, treatment) %>%
mutate(cumSumBmass = cumsum(scaled_mass) ,
cumSumBmassNormalized = cumSumBmass / max(cumSumBmass)*0.999
)
cumSumBmassPlot <- ggplot(data = co2_by_community_scaled, aes(x = representative_bottom, y = cumSumBmassNormalized)) +
geom_line(aes(group = paste(community, plot, treatment, core, sep="-")), color="grey") +
geom_segment(aes(xend = representative_top, yend=cumSumBmassNormalized), color="darkred") +
facet_wrap(community~treatment) +
xlab("Depth (cm)") +
ylab("Cumulative Biomass Sum (proportion)") +
scale_x_reverse() +
coord_flip()
(cumSumBmassPlot)
To calculate total biomass by core I summarised the scaled biomass for each core and divided by the area of the 5.1 cm (=0.051 m) diameter core (\(A = \pi(0.051/2)^2\)).
CO2_community_bg_summary_by_core <- co2_by_community_scaled %>%
group_by(community, plot, treatment, core) %>%
summarise(BGB_total = sum(scaled_mass)/((0.051/2)^2*pi))
bgbTotalPlot <- ggplot(CO2_community_bg_summary_by_core, aes(x=BGB_total, color = community, lty = treatment)) +
geom_density() +
xlab(expression(paste("Total Below Ground Biomass (g m"^"-2",")", sep=""))) +
theme(legend.title = element_blank())
(bgbTotalPlot)
To model the root zone, for each core, I treated the normalized, cumulative belowground biomass (\(C\)) as a function of depth (\(d\)) using the cumulative density function (cdf) for an exponential distribution.
\[ C = 1 - e^{-\lambda d}\]
I solved for \(\lambda\) using the non-linear solver (nls
) in R.
I then extrapolated the maximum rooting depth of 95% of the root mass \(D\), using the quantile for the exponential distribution, using \(\lambda\) and a probability (\(p\)) of 0.95. The max root depth of 95% of the biomass is how exponential root distribution is parameterized in some versions of the marsh equilibrium model (MEM) (Schile et al. 2014).
\[ D = log(1-p)/\lambda \]
# For each unique community, plot, core
for (i in 1:nrow(CO2_community_bg_summary_by_core)) {
depth_series_i <- filter(co2_by_community_scaled,
community == CO2_community_bg_summary_by_core$community[i] &
plot == CO2_community_bg_summary_by_core$plot[i] &
core == CO2_community_bg_summary_by_core$core[i]) %>%
filter(complete.cases(.))
# Fit the CDF for an exponential distribution
# {1 - exp(-lambda * x)
f1 <- formula("cumSumBmassNormalized~(1-exp(-lambda * representative_bottom))")
model_i <- nls(f1, data = depth_series_i, start = list(lambda = 0.05))
lambda_i <- coef(model_i)[1]
# Then get the quantile for p = 0.95
# - (log(1-p)/lambda)
max_rooting_depth_i <- - (log(1-0.95)/lambda_i)
# Save and add to file
CO2_community_bg_summary_by_core$max_rooting_depth[i] <- max_rooting_depth_i
}
MaxRootingDepthPlot <- ggplot(CO2_community_bg_summary_by_core,
aes(x=max_rooting_depth, color = community, lty = treatment)) +
geom_density() +
xlab("95% Max Rooting Depth (cm)") +
theme(legend.title = element_blank())
(MaxRootingDepthPlot)
I used the the lme4
package (Bates et al. 2015) to fit hierarchical linear models, and the lmerTest
package (Kuznetsova, Brockhoff, and Christensen 2017) to test the significance of random effects. I assumed normality for response variables based on my visual inspection of their density plots. I fit linear models with the experimental treatement as the independent variable and total belowground biomass or max rooting depth as the dependent variable. I treated plant community as a random effect.
bg_total_test <- lmer(BGB_total ~ treatment + (1|community), data = CO2_community_bg_summary_by_core)
summary(bg_total_test)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: BGB_total ~ treatment + (1 | community)
## Data: CO2_community_bg_summary_by_core
##
## REML criterion at convergence: 640
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.72275 -0.57512 -0.01722 0.50231 2.74737
##
## Random effects:
## Groups Name Variance Std.Dev.
## community (Intercept) 1228554 1108.4
## Residual 945347 972.3
## Number of obs: 40, groups: community, 2
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 2725.514 813.354 1.075 3.351 0.1705
## treatmentElevated 767.126 307.465 37.000 2.495 0.0172 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## trtmntElvtd -0.189
ranova(bg_total_test)
## ANOVA-like table for random-effects: Single term deletions
##
## Model:
## BGB_total ~ treatment + (1 | community)
## npar logLik AIC LRT Df Pr(>Chisq)
## <none> 4 -319.99 647.98
## (1 | community) 3 -328.24 662.49 16.509 1 4.843e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Total below ground biomass was significantly (p=0.0172) and positively affected by the experimental treatement. Spartina patens had significantly less below ground biomass than Scirpus olneyi (p<0.0001).
root_depth_test <- lmer(max_rooting_depth ~ treatment + (1|community), data = CO2_community_bg_summary_by_core)
## boundary (singular) fit: see ?isSingular
summary(root_depth_test)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: max_rooting_depth ~ treatment + (1 | community)
## Data: CO2_community_bg_summary_by_core
##
## REML criterion at convergence: 321.9
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.8110 -0.6985 -0.1787 0.5552 2.9876
##
## Random effects:
## Groups Name Variance Std.Dev.
## community (Intercept) 0.0 0.00
## Residual 238.5 15.44
## Number of obs: 40, groups: community, 2
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 50.403 3.453 38.000 14.60 <2e-16 ***
## treatmentElevated -2.782 4.883 38.000 -0.57 0.572
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## trtmntElvtd -0.707
## convergence code: 0
## boundary (singular) fit: see ?isSingular
ranova(root_depth_test)
## ANOVA-like table for random-effects: Single term deletions
##
## Model:
## max_rooting_depth ~ treatment + (1 | community)
## npar logLik AIC LRT Df Pr(>Chisq)
## <none> 4 -160.93 329.85
## (1 | community) 3 -160.93 327.85 0 1 1
While in the plots, it appeared that maximum root depth was shallower for the experimental treatment, this difference was not significant (p=0.572), and maximum rooting depth was indistinguishable between species (p=1).
Bates, Douglas, Martin Mächler, Ben Bolker, and Steve Walker. 2015. “Fitting Linear Mixed-Effects Models Using lme4.” Journal of Statistical Software 67 (1): 1–48. doi:10.18637/jss.v067.i01.
Kuznetsova, Alexandra, Per B. Brockhoff, and Rune H. B. Christensen. 2017. “lmerTest Package: Tests in Linear Mixed Effects Models.” Journal of Statistical Software 82 (13): 1–26. doi:10.18637/jss.v082.i13.
R Core Team. 2019. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Schile, Lisa M, John C Callaway, James T Morris, Diana Stralberg, V Thomas Parker, and Maggi Kelly. 2014. “Modeling Tidal Marsh Distribution with Sea-Level Rise: Evaluating the Role of Vegetation, Sediment, and Upland Habitat in Marsh Resiliency.” PloS One 9 (2). Public Library of Science: e88760.
Wickham, Hadley. 2017. Tidyverse: Easily Install and Load the ’Tidyverse’. https://CRAN.R-project.org/package=tidyverse.