library(tidyverse) # for working with ease
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6 ✔ purrr 0.3.4
## ✔ tibble 3.1.8 ✔ dplyr 1.0.10
## ✔ tidyr 1.2.0 ✔ stringr 1.4.1
## ✔ readr 2.1.2 ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
library(metafor) # for meta analysis
## Loading required package: Matrix
##
## Attaching package: 'Matrix'
##
## The following objects are masked from 'package:tidyr':
##
## expand, pack, unpack
##
## Loading required package: metadat
##
## Loading the 'metafor' package (version 3.8-1). For an
## introduction to the package please type: help(metafor)
library(MAd) # for meta analysis
Load and interpret MESI data files.
## second line provides units
col_names <- names(read_csv("~/mesi-db/data/mesi_main.csv", n_max = 0))
units <- names(read_csv("~/mesi-db/data/mesi_main.csv", n_max = 0, skip = 1))
df_units <- tibble(column = col_names,
units = units
)
df <- read_csv("~/mesi-db/data/mesi_main.csv", col_names = col_names, skip = 2)
## Warning: One or more parsing issues, see `problems()` for details
Select experiments from which we will use data.
df0 <- df %>%
## CO2-only manipulation (no other factors manipulated, no crossed manipulation)
filter(treatment == "c") %>%
## only experiments conducted in the field
filter(experiment_type == "field") %>%
## use only free air CO2 enrichment experiments and open-top chambers
filter(fumigation_type %in% c("face", "otc"))
Issues
Let’s use just data from CO2-only experiments that lasted at least three years.
use_exp <- df0 %>%
filter(!is.na(sampling_year)) %>%
group_by(exp) %>%
summarise(nyears = max(sampling_year)) %>%
filter(nyears >= 3) %>%
pull(exp)
# df1 <- df0 %>%
# filter(exp %in% use_exp)
## xxx try: do not subset to minimum experiment length
df1 <- df0
Issues:
## create own variable names (myvar), grouping available variables
use_response <- c("asat", "vcmax", "jmax", "gpp", "gs", "leaf_n", "leaf_cn", "anpp", "agb", "leaf_biomass", "lai", "lai_max", "leaf_area", "bgb", "fine_root_biomass", "root_production", "fine_root_production", "root_shoot_ratio", "soil_no3-n", "soil_nh4-n", "soil_nh4", "soil_no3", "soil_solution_nh4", "soil_solution_no3", "root_n_uptake", "root_nh4_uptake", "root_no3_uptake")
df2 <- df1 %>%
filter(response %in% use_response) %>%
mutate(myvar = response) %>%
## variables re-grouped by myself
mutate(myvar = ifelse(myvar %in% c("agb", "agb_coarse"), "agb", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("bgb", "fine_root_biomass", "coarse_root_c_stock", "bgb_coarse"), "bgb", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("lai", "lai_max"), "lai", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("bgb", "fine_root_biomass"), "bgb", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("root_production", "fine_root_production", "coarse_root_production"),
"root_production",
myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("root_n_uptake", "root_nh4_uptake", "root_no3_uptake"),
"n_uptake",
myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("soil_no3-n", "soil_nh4-n", "soil_nh4", "soil_no3", "soil_solution_nh4", "soil_solution_no3"),
"n_inorg",
myvar))
use_vars <- unique(df2$myvar)
Test analysis and plot of ANPP data. Calculate the response ratio of
ANPP (mean and variance) for each experiment. To get that, we first need
to calcuate the means and standard deviation for the ambient and
elevated levels, pooling multiple measurements (years, sampling dates),
each given with mean \(\mu_i\), number
\(N_i\) (replicates/plots), and
standard deviation \(\sigma_i\) or
standard error. For the function metafor::escalc()
, we need
standard deviations (\(SD\)). Calculate
them for those rows where only standard errors \(SE\) are given as: \[
SD = SE \sqrt{N}
\]
Calculate "ROM"
- the log transformed ratio of means
(Hedges et al., 1999; Lajeunesse, 2011) for each observation pair
(ambient and elevated).
df3 <- df2 %>%
## keep only essential variables and drop rows containing missing values for essential variables
select(id, exp, myvar, treatment, sampling_year, x_t, x_c, sd_t, sd_c, rep_t, rep_c) %>%
## Get logarithm of response ratio and its variance
metafor::escalc(
measure = "ROM",
m1i = x_t, sd1i = sd_t, n1i = rep_t,
m2i = x_c, sd2i = sd_c, n2i = rep_c,
data = .,
append = TRUE,
var.names = c("logr", "logr_var")
) %>%
## to keep the output readable from the console output
as_tibble() %>%
## get standard error
mutate( logr_se = sqrt(logr_var) / sqrt(rep_t) )
## Warning: Some 'yi' and/or 'vi' values equal to +-Inf. Recoded to NAs.
# ## data reduction here!
# tmp3 <- purrr::map(as.list(use_vars), ~agg_by_var(., df3))
# names(tmp3) <- use_vars
# tmp3$root_shoot_ratio
Aggregate all measurements (multiple years, sampling dates and plots) by experiment (and response variable - although here only one) for meta analysis.
df4 <- df3 %>%
filter(!is.na(logr_var) & !is.na(logr)) %>%
# re-create ID (common ID per experiment and response variable)
select(-id) %>%
mutate( id = paste(exp, myvar, sep = "_XXX_")) %>%
MAd::agg(
id = id,
es = logr,
var = logr_var,
cor = 1.0,
method = "BHHR",
data = .
) %>%
## to keep the output readable from the console output
as_tibble() %>%
# separate ID again for ease of data use
mutate( id = str_split(id, "_XXX_") ) %>%
mutate( exp = purrr::map_chr(id, 1),
myvar = purrr::map_chr(id, 2) ) %>%
## rename again
select(exp, myvar, logr = es, logr_var = var) %>%
## add number of observations (sum of plots and repeated samplings)
left_join(
df3 %>%
group_by(exp, myvar, treatment) %>%
summarise(n_c = sum(rep_c), n_t = sum(rep_t)),
by = c("exp", "myvar")
) %>%
## get standard error. Verify if number available observations are identical
## for ambient and elevated. Use N from control here (n_c).
mutate( logr_se = sqrt(logr_var) / sqrt(n_c) )
## `summarise()` has grouped output by 'exp', 'myvar'. You can override using the
## `.groups` argument.
# tmp <- purrr::map(as.list(use_vars), ~agg_by_var(., df4 %>% rename(rep_c = n_c)))
# names(tmp) <- use_vars
# tmp$root_shoot_ratio
Aggregate log-ratios across multiple experiments, taking into account their respective variance and using the experiment identity as a grouping factor for random intercepts.
source("~/lt_cn_review/R/analyse_meta.R")
out <- purrr::map(as.list(use_vars), ~analyse_meta(df4 %>% rename(var = myvar), nam_target = .))
names(out) <- use_vars
df_box <- purrr::map_dfr(out, "df_box")
Number of data points (plot-level measurements) per variable:
df4 %>%
group_by(myvar) %>%
summarise(n_plots = sum(n_c), n_exp = n()) %>%
rename_("Variable"="myvar", "N plots"="n_plots", "N experiments"="n_exp") %>%
knitr::kable()
## Warning: `rename_()` was deprecated in dplyr 0.7.0.
## Please use `rename()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
Variable | N plots | N experiments |
---|---|---|
agb | 1715 | 61 |
anpp | 336 | 22 |
asat | 553 | 19 |
bgb | 1237 | 50 |
gpp | 128 | 7 |
gs | NA | 17 |
jmax | 205 | 7 |
lai | NA | 17 |
leaf_area | 78 | 6 |
leaf_biomass | 426 | 16 |
leaf_cn | 105 | 5 |
leaf_n | 1801 | 17 |
n_inorg | NA | 5 |
n_uptake | 52 | 5 |
root_production | 361 | 11 |
root_shoot_ratio | 172 | 16 |
vcmax | 249 | 9 |
Available experiments for root:shoot ratio
ivar <- "root_shoot_ratio"
df4 %>%
filter(myvar == ivar) %>%
select(exp, n_c) %>%
knitr::kable()
exp | n_c |
---|---|
duolun7_c | 12 |
climaite_c | 6 |
46.77_9.87_c | 3 |
swissface_forest_c | 24 |
jrbp_face_c | 8 |
euroface_pooled_c | 3 |
swissface_lolium_c | 6 |
sca_c | 3 |
eucface_c | 3 |
euroface_pa_c | 6 |
euroface_pn_c | 6 |
euroface_pe_c | 6 |
maricopaface_cotton91_c | 68 |
ornl_face_liqui_c | 2 |
swissface_chalk_c | 12 |
maricopaface_wheat94_c | 4 |
Available experiments for inorganic N availability
ivar <- "n_inorg"
df4 %>%
filter(myvar == ivar) %>%
select(exp, n_c) %>%
knitr::kable()
exp | n_c |
---|---|
climaite_c | 54 |
ornl_face_liqui2_c | NA |
dukeface_c | 32 |
euroface_pooled_c | 18 |
riceface_nianyufarm_triticum_2012_c | 30 |
Available experiments for N uptake
ivar <- "n_uptake"
df4 %>%
filter(myvar == ivar) %>%
select(exp, n_c) %>%
knitr::kable()
exp | n_c |
---|---|
climaite_c | 36 |
ornl_face_liqui_c | 2 |
euroface_pooled_c | 6 |
aspenface_c | 6 |
ornl_face_liqui2_c | 2 |
Plot dots and my box.
df4 %>%
## give it a nice order (for plotting)
mutate(myvar = factor(myvar, levels = rev(c("asat", "gpp", "vcmax", "jmax", "gs", "leaf_n", "leaf_cn", "lai", "leaf_area", "leaf_biomass", "anpp", "agb", "root_production", "bgb", "root_shoot_ratio", "n_uptake", "n_inorg")))) %>%
ggplot( aes(x = myvar, y = logr)) +
geom_jitter( color = rgb(0,0,0,0.5), aes( size = 1/logr_se ), position = position_jitter(w = 0.2, h = 0) ) +
geom_crossbar( data = df_box,
aes(x = var, y = middle, ymin = ymin, ymax = ymax),
fill = "tomato", color = "black", alpha = 0.6, width = 0.5
) +
geom_hline( yintercept = 0.0, size = 0.5 ) +
labs(x = "Variable", y = "Log Response Ratio", size = expression(paste("Error"^{-1}))) +
coord_flip() +
# ylim(-1, 1) +
labs(title = "MESI data", subtitle = "Response to eCO2")
## Warning: Removed 6 rows containing missing values (geom_point).
Findings:
asat
) and GPPbgb
) than in
aboveground biomass (agb
) (but outlier in
agb
), Consistent with the positive response in root:shoot
ratio (but large variation between experiments).gs
).Standard forest plots
for (ivar in use_vars){
print(ivar)
try(metafor::forest(out[[ivar]]$modl))
}
## [1] "bgb"
## [1] "leaf_n"
## [1] "gs"
## [1] "asat"
## [1] "agb"
## [1] "gpp"
## [1] "root_shoot_ratio"
## [1] "n_inorg"
## [1] "leaf_biomass"
## [1] "root_production"
## [1] "n_uptake"
## [1] "anpp"
## [1] "vcmax"
## [1] "leaf_cn"
## [1] "jmax"
## [1] "leaf_area"
## [1] "lai"
# purrr::map(as.list(use_vars), ~try(metafor::forest(out[[.]]$modl)))
Issues:
bgb
) was actually measured and not estimated based on
aboveground biomass (or other aboveground observations) and scaling
assumptions (-> KEVIN, STUDENT).agb
and
root_production
and positive outliers for anpp
(-> KEVIN, remove them?)## file generated by cnreview/dataanalysis.Rmd
df_gcme <- readRDS("~/lt_cn_review/data/df_c_agg.rds")
write_csv(df_gcme, file = "~/lt_cn_review/data/df_co2_gcme_usedbybeni.csv")
N uptake
## GCME
df_gcme %>%
filter(my_varnam == "my_nup") %>%
select(exp_nam, my_varnam, n_plots)
## # A tibble: 11 × 3
## exp_nam my_varnam n_plots
## <chr> <chr> <dbl>
## 1 Brandbjerg my_nup 24
## 2 RiceFACE_Japan_A_2003_39,38_140,57 my_nup 36
## 3 RiceFACE_Japan_Ki_2004_39,38_140,57 my_nup 8
## 4 POPFACE_pa my_nup 6
## 5 POPFACE_pe my_nup 6
## 6 POPFACE_pn my_nup 6
## 7 Durham_DukeFACE my_nup 6
## 8 ORNERP_liqui my_nup 2
## 9 Rhine-aspenFACE my_nup 6
## 10 ORNERP_liqui2 my_nup 2
## 11 SwissFACE_lolium2 my_nup 6
## MESI
df4 %>%
filter(myvar == "n_uptake") %>%
select(exp, myvar, n_c)
## # A tibble: 5 × 3
## exp myvar n_c
## <chr> <chr> <dbl>
## 1 climaite_c n_uptake 36
## 2 ornl_face_liqui_c n_uptake 2
## 3 euroface_pooled_c n_uptake 6
## 4 aspenface_c n_uptake 6
## 5 ornl_face_liqui2_c n_uptake 2
Root:shoot ratio
## GCME
df_gcme %>%
filter(my_varnam == "my_rootshootratio") %>%
select(exp_nam, my_varnam, n_plots)
## # A tibble: 18 × 3
## exp_nam my_varnam n_plots
## <chr> <chr> <dbl>
## 1 DRI my_rootshootratio 9
## 2 JRBP_OTCsand my_rootshootratio 4
## 3 JRBP_OTCser my_rootshootratio 4
## 4 MBS_pe my_rootshootratio 5
## 5 MBS_pt my_rootshootratio 4
## 6 ORNERP_liriodendron my_rootshootratio 2
## 7 ORNERP_quercus my_rootshootratio 2
## 8 PHACE my_rootshootratio 15
## 9 POPFACE_pa my_rootshootratio 9
## 10 POPFACE_pe my_rootshootratio 9
## 11 POPFACE_pn my_rootshootratio 9
## 12 SCBG my_rootshootratio 3
## 13 SwissFACE_lolium2 my_rootshootratio 6
## 14 UA_OTC my_rootshootratio 8
## 15 USDA_citrus my_rootshootratio 2
## 16 EUROFACE4_pa my_rootshootratio 3
## 17 EUROFACE4_pe my_rootshootratio 3
## 18 EUROFACE4_pn my_rootshootratio 3
## MESI
df4 %>%
filter(myvar == "n_uptake") %>%
select(exp, myvar, n_c)
## # A tibble: 5 × 3
## exp myvar n_c
## <chr> <chr> <dbl>
## 1 climaite_c n_uptake 36
## 2 ornl_face_liqui_c n_uptake 2
## 3 euroface_pooled_c n_uptake 6
## 4 aspenface_c n_uptake 6
## 5 ornl_face_liqui2_c n_uptake 2
Inorganic N
## GCME
df_gcme %>%
filter(my_varnam == "my_navl") %>%
select(exp_nam, my_varnam, n_plots)
## # A tibble: 20 × 3
## exp_nam my_varnam n_plots
## <chr> <chr> <dbl>
## 1 TasFACE my_navl 189
## 2 MI my_navl 8
## 3 ORNERP_liqui2 my_navl 38
## 4 Headley_fe my_navl 4
## 5 Headley_ps my_navl 4
## 6 Headley_qp my_navl 6
## 7 POPFACE_pa my_navl 6
## 8 POPFACE_pe my_navl 6
## 9 POPFACE_pn my_navl 6
## 10 DUKE my_navl 24
## 11 SwissFACE_lolium2 my_navl 126
## 12 EucFACE my_navl 228
## 13 POPFACE_pooled my_navl 36
## 14 EUROFACE7_pooled my_navl 144
## 15 Brandbjerg my_navl 252
## 16 BioCON my_navl 69
## 17 GiFACE my_navl 441
## 18 DUKE2 my_navl 56
## 19 RiceFACE_China_32N_120E_Tr_1 my_navl 90
## 20 DRI my_navl 30
## MESI
df4 %>%
filter(myvar == "n_inorg") %>%
select(exp, myvar, n_c)
## # A tibble: 5 × 3
## exp myvar n_c
## <chr> <chr> <dbl>
## 1 climaite_c n_inorg 54
## 2 ornl_face_liqui2_c n_inorg NA
## 3 dukeface_c n_inorg 32
## 4 euroface_pooled_c n_inorg 18
## 5 riceface_nianyufarm_triticum_2012_c n_inorg 30
Data in GCME from:
df_navl <- read_rds("~/lt_cn_review/data/df_navl.rds")
df_navl %>% select(prev_name, Data_type, Fumigation_type, Source_Reference)
## # A tibble: 60 × 4
## prev_name Data_type Fumigation_type Source_Reference
## <chr> <chr> <chr> <chr>
## 1 EucFACE_c soil_mineral_N FACE Hasegawa et al 2016
## 2 EucFACE_c soil_mineral_N FACE Ochoa-Hueso et al 2017
## 3 EUROFACE7_pooled_c soil_mineral_N FACE Moscatelli et al 2005b
## 4 POPFACE_pa_c soil_mineral_N FACE Calfapietera et al 2003a
## 5 POPFACE_pe_c soil_mineral_N FACE Calfapietera et al 2003a
## 6 POPFACE_pn_c soil_mineral_N FACE Calfapietera et al 2003a
## 7 POPFACE_pooled_c soil_mineral_N FACE Moscatelli et al 2005a
## 8 POPFACE_pooled_c soil_mineral_N FACE Moscatelli et al 2005b
## 9 SwissFACE_lolium2_c soil_mineral_N FACE Fromin et al 2005
## 10 TasFACE_c soil_mineral_N FACE Hayden et al. 2012
## # … with 50 more rows
Plot effect sizes for two different variables against each other, given that data is available for both variables for a given experiment.
## make a wide table with ANPP and BNPP
df4_anpp_bnpp <- df4 %>%
filter(myvar %in% c("anpp", "root_production")) %>%
select(exp, myvar, logr) %>%
tidyr::spread( myvar, logr )
## add standard error
df4_anpp_bnpp <- df4 %>%
filter(myvar %in% c("anpp", "root_production")) %>%
select(exp, myvar, logr_se) %>%
tidyr::spread( myvar, logr_se ) %>%
rename(se_anpp = anpp, se_root_production = root_production) %>%
right_join(df4_anpp_bnpp, by = "exp") %>%
mutate(se = se_anpp * se_root_production)
df4_anpp_bnpp %>%
ggplot(aes(x = anpp, y = root_production, label = exp)) +
geom_point(aes(size = 1/se), color = "tomato") +
xlim(0, 0.8) + ylim(0, 0.8) +
geom_abline(linetype = "dotted") +
ggrepel::geom_text_repel(size = 3, point.padding = 0.5, segment.alpha = 0, color = "grey50") +
labs(x = "Log RR of ANPP", y = "Log RR of root production", size = expression(paste("Error"^{-1}))) +
theme_classic()
## Warning: Removed 19 rows containing missing values (geom_point).
## Warning: Removed 19 rows containing missing values (geom_text_repel).
## make a wide table with ANPP and BNPP
df4_agb_bnpp <- df4 %>%
filter(myvar %in% c("agb", "bgb")) %>%
select(exp, myvar, logr) %>%
tidyr::spread( myvar, logr )
## add standard error
df4_agb_bnpp <- df4 %>%
filter(myvar %in% c("agb", "bgb")) %>%
select(exp, myvar, logr_se) %>%
tidyr::spread( myvar, logr_se ) %>%
rename(se_agb = agb, se_bgb = bgb) %>%
right_join(df4_agb_bnpp, by = "exp") %>%
mutate(se = se_agb * se_bgb)
df4_agb_bnpp %>%
ggplot(aes(x = agb, y = bgb, label = exp)) +
geom_point(aes(size = 1/se), color = "tomato") +
xlim(0, 0.6) + ylim(0, 0.6) +
geom_abline(linetype = "dotted") +
ggrepel::geom_text_repel(size = 3, point.padding = 0.5, segment.alpha = 0, color = "grey50") +
labs(x = "Log RR of AGB", y = "Log RR of BGB", size=expression(paste("Error"^{-1}))) +
theme_classic()
## Warning: Removed 52 rows containing missing values (geom_point).
## Warning: Removed 52 rows containing missing values (geom_text_repel).
Issues:
Select experiments from which we will use data.
df0 <- df %>%
## fertilisation experiments only
filter(treatment == "f") %>%
## only experiments conducted in the field
filter(experiment_type == "field")
Same as above
use_exp <- df0 %>%
filter(!is.na(sampling_year)) %>%
group_by(exp) %>%
summarise(nyears = max(sampling_year)) %>%
filter(nyears >= 3) %>%
pull(exp)
# df1 <- df0 %>%
# filter(exp %in% use_exp)
## xxx try: do not subset to minimum experiment length
df1 <- df0
## select variables only variables as used for CO2 analysis and not provided by Liang et al.
## create own variable names (myvar), grouping available variables
use_response <- c("anpp", "agb", "bgb", "fine_root_biomass", "root_production", "fine_root_production", "root_shoot_ratio", "soil_no3-n", "soil_nh4-n", "soil_nh4", "soil_no3", "soil_solution_nh4", "soil_solution_no3", "root_n_uptake", "root_nh4_uptake", "root_no3_uptake")
df2 <- df1 %>%
filter(response %in% use_response) %>%
mutate(myvar = response) %>%
## variables re-grouped by myself
## variables re-grouped by myself
mutate(myvar = ifelse(myvar %in% c("agb", "agb_coarse"), "agb", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("bgb", "fine_root_biomass", "coarse_root_c_stock", "bgb_coarse"), "bgb", myvar)) %>%
# mutate(myvar = ifelse(myvar %in% c("lai", "lai_max"), "lai", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("bgb", "fine_root_biomass"), "bgb", myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("root_production", "fine_root_production", "coarse_root_production"),
"root_production",
myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("root_n_uptake", "root_nh4_uptake", "root_no3_uptake"),
"n_uptake",
myvar)) %>%
mutate(myvar = ifelse(myvar %in% c("soil_no3-n", "soil_nh4-n", "soil_nh4", "soil_no3", "soil_solution_nh4", "soil_solution_no3"),
"n_inorg",
myvar))
use_vars <- unique(df2$myvar)
Calculate "ROM"
- the log transformed ratio of means
(Hedges et al., 1999; Lajeunesse, 2011) for each observation pair
(ambient and elevated).
df3 <- df2 %>%
## keep only essential variables and drop rows containing missing values for essential variables
select(id, exp, myvar, treatment,sampling_year, x_t, x_c, sd_t, sd_c, rep_t, rep_c) %>%
## Get logarithm of response ratio and its variance
metafor::escalc(
measure = "ROM",
m1i = x_t, sd1i = sd_t, n1i = rep_t,
m2i = x_c, sd2i = sd_c, n2i = rep_c,
data = .,
append = TRUE,
var.names = c("logr", "logr_var")
) %>%
## to keep the output readable from the console output
as_tibble() %>%
## get standard error
mutate( logr_se = sqrt(logr_var) / sqrt(rep_t) )
## Warning in log(m1i/m2i): NaNs produced
## Warning: Some 'yi' and/or 'vi' values equal to +-Inf. Recoded to NAs.
Aggregate all measurements (multiple years, sampling dates and plots) by experiment (and response variable - although here only one) for meta analysis.
df4 <- df3 %>%
filter(!is.na(logr_var) & !is.na(logr)) %>%
# re-create ID (common ID per experiment and response variable)
select(-id) %>%
mutate( id = paste(exp, myvar, sep = "_XXX_")) %>%
MAd::agg(
id = id,
es = logr,
var = logr_var,
cor = 1.0,
method = "BHHR",
data = .
) %>%
## to keep the output readable from the console output
as_tibble() %>%
# separate ID again for ease of data use
mutate( id = str_split(id, "_XXX_") ) %>%
mutate( exp = purrr::map_chr(id, 1),
myvar = purrr::map_chr(id, 2) ) %>%
## rename again
select(exp, myvar, logr = es, logr_var = var) %>%
## add number of observations (sum of plots and repeated samplings)
left_join(
df3 %>%
group_by(exp, myvar, treatment) %>%
summarise(n_c = sum(rep_c), n_t = sum(rep_t)),
by = c("exp", "myvar")
) %>%
## get standard error. Verify if number available observations are identical
## for ambient and elevated. Use N from control here (n_c).
mutate( logr_se = sqrt(logr_var) / sqrt(n_c) )
## `summarise()` has grouped output by 'exp', 'myvar'. You can override using the
## `.groups` argument.
Aggregate log-ratios across multiple experiments, taking into account their respective variance and using the experiment identity as a grouping factor for random intercepts.
source("~/lt_cn_review/R/analyse_meta.R")
out <- purrr::map(as.list(use_vars), ~analyse_meta(df4 %>% rename(var = myvar), nam_target = .))
names(out) <- use_vars
df_box <- purrr::map_dfr(out, "df_box")
Number of data points (plot-level measurements) per variable:
df4 %>%
group_by(myvar) %>%
summarise(n_plots = sum(n_c), n_exp = n()) %>%
rename_("Variable"="myvar", "N observations"="n_plots", "N experiments"="n_exp") %>%
knitr::kable()
Variable | N observations | N experiments |
---|---|---|
agb | 5957 | 237 |
anpp | NA | 50 |
bgb | 1580 | 109 |
n_inorg | 1043 | 52 |
n_uptake | 102 | 4 |
root_production | 374 | 21 |
root_shoot_ratio | 149 | 25 |
Number of data points (plot-level measurements) per experiment:
df4 %>%
group_by(exp) %>%
summarise(n_plots = sum(n_c), n_exp = n()) %>%
rename_("Experiment"="exp", "N observations"="n_plots", "N experiments"="n_exp") %>%
knitr::kable()
Experiment | N observations | N experiments |
---|---|---|
-43.52_172.58_f | 5 | 1 |
34.2_106.43_f | 10 | 1 |
35.9_-79.03_f | 3 | 1 |
37.25_-121.75_forb_fn | 3 | 1 |
37.25_-121.75_forb_fnp | 3 | 1 |
37.25_-121.75_forb_fp | 3 | 1 |
37.25_-121.75_grass_fn | 3 | 1 |
37.25_-121.75_grass_fnp | 3 | 1 |
37.25_-121.75_grass_fp | 3 | 1 |
38.53_-76.33_f | 50 | 2 |
38.883_-107.033_f | 24 | 1 |
40.4_-86.9_f | 9 | 1 |
41.77_111.88_f | 24 | 1 |
44.1_-96.41_f | 8 | 1 |
47.26_8.31_f | 4 | 1 |
47.26_8.31_f2 | 8 | 1 |
47.26_8.31_f3 | 8 | 1 |
68.38_-104.54_f | 4 | 1 |
69.05_20.88_f | 21 | 1 |
abag_degraded_f | 36 | 1 |
abag_degraded_f2 | 36 | 1 |
abag_degraded_f3 | 36 | 1 |
abag_degraded_f4 | 36 | 1 |
abag_degraded_f5 | 36 | 1 |
abag_f | 38 | 2 |
abag_f2 | 83 | 4 |
abag_f3 | 83 | 4 |
abag_f4 | 83 | 4 |
abag_f5 | 83 | 4 |
abag_mature_f | 72 | 2 |
abag_mature_f2 | 72 | 2 |
abag_mature_f3 | 72 | 2 |
abag_mature_f4 | 72 | 2 |
abag_mature_f5 | 72 | 2 |
alaska_f | 12 | 2 |
alp_weissenstein2_f | 130 | 3 |
antu_f | 12 | 1 |
antu_f2 | 12 | 1 |
arizona_f | 16 | 1 |
bcnm_fk | 20 | 1 |
bcnm_fn | 20 | 1 |
bcnm_fnk | 20 | 1 |
bcnm_fnp | 20 | 1 |
bcnm_fnpk | 20 | 1 |
bcnm_fp | 20 | 1 |
bcnm_fpk | 20 | 1 |
bennekom_drained_fn | 25 | 1 |
bennekom_drained_fnp | 5 | 1 |
bennekom_drained_fp | 5 | 1 |
bennekom_undrained_fn | 25 | 1 |
bennekom_undrained_fnp | 5 | 1 |
bennekom_undrained_fp | 5 | 1 |
biocon_f | 238 | 6 |
bleckstugan_f | 1 | 1 |
bonanza_creek_2005_f | 108 | 1 |
bordeaux_f | 24 | 1 |
bordeaux_f2 | 24 | 1 |
changbai_mountain_f | 6 | 1 |
changbai_mountain_f2 | 18 | 2 |
changshan_f | 200 | 2 |
chaux-des-breuleux_f | 25 | 3 |
chiriqui_f | 8 | 1 |
chubut_f | 91 | 1 |
climaite_f | 6 | 1 |
climaite_f2 | 6 | 1 |
cuiliugou_f | 240 | 2 |
damxung_2013_f | 24 | 2 |
damxung_2014_f | 48 | 1 |
damxung_2014_f2 | 48 | 1 |
damxung_2014_f3 | 48 | 1 |
damxung_2015_f | 476 | 1 |
damxung_b_f | 46 | 2 |
damxung_b_f2 | 39 | 2 |
damxung_b_f3 | 20 | 2 |
damxung_f | 120 | 2 |
daqinggou_fn | 36 | 2 |
daqinggou_fnp | 12 | 2 |
daqinggou_fp | 12 | 2 |
dbr2_f | 12 | 2 |
dbr2_f2 | 12 | 2 |
dbr2_f3 | 12 | 2 |
dbr2_f4 | 12 | 2 |
deqing_b_f | 15 | 1 |
deqing_b_f3 | 27 | 1 |
deqing_d_f | 21 | 1 |
deqing_d_f2 | 24 | 1 |
deqing_d_f3 | 21 | 1 |
deqing_f | 5 | 1 |
deqing_f2 | 5 | 1 |
dukeface_f | 4 | 1 |
duolun_2010b_f | 55 | 5 |
duolun1_f | 88 | 4 |
duolun12_f | 10 | 1 |
duolun15_fn | 4 | 1 |
duolun15_fn2 | 4 | 1 |
duolun15_fn2p | 4 | 1 |
duolun15_fnp | 4 | 1 |
duolun2_f | 24 | 1 |
duolun2_f2 | 64 | 1 |
duolun2_f3 | 24 | 1 |
duolun2_f4 | 64 | 1 |
duolun2_f5 | 64 | 1 |
duolun2_f6 | 69 | 2 |
duolun2_f7 | 24 | 1 |
duolun3_f | 185 | 1 |
duolun3_f2 | 175 | 1 |
duolun3_f3 | 185 | 1 |
duolun3_f4 | 185 | 1 |
duolun3_f5 | 185 | 1 |
duolun4_f | 32 | 2 |
duolun7_f | 161 | 4 |
duolun9_f | 132 | 5 |
duolun9_w | 6 | 1 |
eastern_japan_f | 10 | 1 |
euroface_pa_f | 27 | 3 |
euroface_pe_f | 27 | 3 |
euroface_pn_f | 27 | 3 |
euroface_pooled_f | 54 | 2 |
flakaliden_f | 18 | 2 |
flakaliden_f2 | 4 | 1 |
fruebuel2_f | 190 | 3 |
gaoyao_f | 4 | 1 |
gaoyao_f2 | 4 | 1 |
gaoyao_f3 | 8 | 1 |
haeggsjoeliden_f | 1 | 1 |
hamr_f | 8 | 3 |
hamr_f2 | 8 | 3 |
harbin_f | 18 | 3 |
hawaii_fn | 10 | 1 |
hf_f_mh_f | 3 | 1 |
hf_f_mh_f2 | 3 | 1 |
hf_f_pr_f | 3 | 1 |
hf_f_pr_f2 | 3 | 1 |
horqin_zuoyi_houqi_f | 12 | 1 |
horqin_zuoyi_houqi_f2 | 12 | 1 |
horqin_zuoyi_houqi_f3 | 12 | 1 |
horqin_zuoyi_houqi_f4 | 12 | 1 |
horqin_zuoyi_houqi_f5 | 12 | 1 |
horsham_face10bc_f | 4 | 1 |
horsham_face10bk_f | 4 | 1 |
imgers_hg_2005_f | 96 | 3 |
imgers_hg_2005_f2 | 96 | 3 |
imgers_hg_2008_f | 32 | 3 |
imgers_hg_d_2008_f | 2 | 1 |
imgers_lg_d_2008_f | 2 | 1 |
imgers_mg_2008_f | 36 | 3 |
imgers_mg_d_2007_f | 2 | 1 |
imgers_ng_2006_f | 6 | 1 |
imgers_ng_2006_f2 | 6 | 1 |
imgers_ng_2006_f3 | 6 | 1 |
imgers_ng_2006_f4 | 6 | 1 |
imgers_ng_2006_f5 | 6 | 1 |
imgers_ng_2007b_f | 40 | 3 |
imgers_ng_d_2007_f | 2 | 1 |
imgers_pooled_2005_f | 16 | 2 |
imgers_pooled_2006_f | 8 | 1 |
imgers_pooled_2006_f2 | 8 | 1 |
imgers_pooled_2008c_f | 4 | 1 |
irvine_ranch_1_f | 45 | 5 |
itatinga_f | 15 | 1 |
itatinga_f2 | 15 | 1 |
jilin_f | 16 | 2 |
jingtai_f | 56 | 2 |
jingtai_f2 | 64 | 2 |
jingtai_f3 | 64 | 2 |
jrbp_face_f | 184 | 5 |
kemijaervi_f | 1 | 1 |
kisa_grahamiana_f | 20 | 1 |
liaoning_f | 6 | 1 |
liudaogou_f | 72 | 2 |
liujiang_b_f | 3 | 1 |
liujiang_b_f2 | 3 | 1 |
liujiang_b_f3 | 3 | 1 |
luangcheng_f | 9 | 1 |
luneburg_field_2006_fn | 10 | 1 |
luneburg_field_2006_fnp | 10 | 1 |
luneburg_field_2006_fp | 10 | 1 |
luneburg_field_2008_fn | 10 | 1 |
luneburg_field_2008_fnp | 10 | 1 |
luneburg_field_2008_fp | 10 | 1 |
maoershan_fraxinus_f | 3 | 1 |
maoershan_larix_f | 33 | 3 |
maoxian_f | 36 | 3 |
maoxian_pc_f | 5 | 1 |
maoxian_pp_f | 5 | 1 |
massachusetts_f | 80 | 1 |
massachusetts_f2 | 80 | 1 |
mbs_pt2_f | 10 | 1 |
menyuan_b_f | 12 | 1 |
menyuan_b_f2 | 12 | 1 |
menyuan_f | 14 | 2 |
menyuan_f2 | 14 | 2 |
menyuan_f3 | 14 | 2 |
menyuan_f4 | 14 | 2 |
menyuan_f5 | 14 | 2 |
menyuan_f6 | 14 | 2 |
menyuan_f62 | 14 | 2 |
menyuan_f63 | 14 | 2 |
menyuan_f64 | 19 | 2 |
michigan_c_f | 3 | 1 |
michigan_e_f | 36 | 1 |
michigan_pooled_f | 3 | 1 |
michigan-kbs_grassland_f | 120 | 1 |
michigana_f | 15 | 2 |
michiganb_f | 3 | 1 |
michiganc_f | 18 | 3 |
niwot_ridge2_dm_f2np | 5 | 1 |
niwot_ridge2_dm_fn | 35 | 3 |
niwot_ridge2_dm_fnp | 10 | 2 |
niwot_ridge2_dm_fp | 10 | 2 |
niwot_ridge2_wm_fn | 25 | 3 |
niwot_ridge2_wm_fnp | 15 | 2 |
niwot_ridge2_wm_fp | 10 | 2 |
norrliden_f | 3 | 1 |
norrliden_f2 | 3 | 1 |
norrliden_f3 | 3 | 1 |
norrliden_f4 | 3 | 1 |
norrliden_f5 | 3 | 1 |
norrliden_f6 | 3 | 1 |
ornl_face_liqui2_f | 19 | 3 |
ottawa_fn | 3 | 1 |
ottawa_fn2 | 3 | 1 |
ottawa_fn3 | 3 | 1 |
pepeekeo_f | NA | 3 |
puerto_b_f | 3 | 1 |
reckenholz_f | 24 | 1 |
riceface_nianyufarm_2002_f | 3 | 1 |
riceface_nianyufarm_2003_f | 3 | 1 |
riceface_zhongcun_2008_f | 9 | 1 |
riceface_zhongcun_hybrid_2006_f | 18 | 1 |
rosinedal_f | 26 | 3 |
rosinedal_f2 | 20 | 1 |
salmisuo_f | 25 | 3 |
sanjiang_mire_maize_fn | 6 | 2 |
sanjiang_mire_maize_fn2 | 6 | 2 |
sanjiang_mire_nfert2_f | 3 | 1 |
sanjiang_mire_nfert2_f2 | 6 | 1 |
sanjiang_mire_nfert2_f3 | 6 | 1 |
sanjiang_mire_pfert_fp | 9 | 1 |
sanjiang_mire_pfert_fp2 | 9 | 1 |
sanjiang_mire_pfert_fp3 | 9 | 1 |
santa_rosa_f | 24 | 1 |
santa_rosa_f2 | 24 | 1 |
santa_rosa_f3 | 24 | 1 |
sarobetsu_f | 27 | 1 |
sarobetsu_f2 | 27 | 1 |
sarobetsu_f3 | 27 | 1 |
sarobetsu_f4 | 27 | 1 |
sca_f | 24 | 2 |
scbg_f | 6 | 2 |
schiermonnikoog_old_fn | 48 | 1 |
schiermonnikoog_old_fn2 | 48 | 1 |
schiermonnikoog_old_fn2p | 12 | 1 |
schiermonnikoog_old_fn2p2 | 12 | 1 |
schiermonnikoog_old_fnp | 12 | 1 |
schiermonnikoog_old_fnp2 | 12 | 1 |
schiermonnikoog_old_fp | 12 | 1 |
schiermonnikoog_old_fp2 | 12 | 1 |
schiermonnikoog_young_fn | 48 | 1 |
schiermonnikoog_young_fn2 | 48 | 1 |
schiermonnikoog_young_fn2p | 12 | 1 |
schiermonnikoog_young_fn2p2 | 12 | 1 |
schiermonnikoog_young_fnp | 12 | 1 |
schiermonnikoog_young_fnp2 | 12 | 1 |
schiermonnikoog_young_fp | 12 | 1 |
schiermonnikoog_young_fp2 | 12 | 1 |
shaaxi_330_bungeana_fn | 3 | 1 |
shaaxi_330_bungeana_fn3 | 6 | 1 |
shaaxi_330_bungeana_fnp | 3 | 1 |
shaaxi_330_bungeana_fp | 3 | 1 |
shaaxi_330_davarica_fn | 3 | 1 |
shaaxi_330_davarica_fn3 | 6 | 1 |
shaaxi_330_davarica_fnp | 3 | 1 |
shaaxi_330_davarica_fp | 3 | 1 |
shaaxi_330_fn | 6 | 1 |
shaaxi_330_fn2 | 3 | 1 |
shaaxi_330_fn3 | 9 | 1 |
shaaxi_330_fnp | 3 | 1 |
shaaxi_330_fp | 3 | 1 |
shaaxi_6_bungeana_fn | 3 | 1 |
shaaxi_6_bungeana_fn2 | 3 | 1 |
shaaxi_6_bungeana_fn3 | 3 | 1 |
shaaxi_6_bungeana_fn3p | 3 | 1 |
shaaxi_6_bungeana_fp | 3 | 1 |
shaaxi_6_davarica_fn | 3 | 1 |
shaaxi_6_davarica_fn2 | 3 | 1 |
shaaxi_6_davarica_fn3 | 3 | 1 |
shaaxi_6_davarica_fn3p | 3 | 1 |
shaaxi_6_davarica_fp | 3 | 1 |
shaaxi_6_fn | 6 | 1 |
shaaxi_6_fn2 | 6 | 1 |
shaaxi_6_fn3 | 6 | 1 |
shaaxi_6_fn3p | 3 | 1 |
shaaxi_6_fp | 3 | 1 |
shaxian_f | 9 | 2 |
shaxian_f2 | 9 | 2 |
shaxian_f3 | 9 | 2 |
silwood_f | 80 | 1 |
sjaellirimsheden_f | 1 | 1 |
skogaby_f2 | 4 | 1 |
slattatjakka_f | 80 | 1 |
sodankylae_f | 1 | 1 |
songen_f | 96 | 2 |
strasan_f | 2 | 1 |
strasan_f2 | 2 | 1 |
strasan_f3 | 2 | 1 |
swissface_lolium2_f | 30 | 4 |
swissface_loliumtrifolium2_f | 18 | 2 |
swissface_trifolium2_f | 30 | 4 |
sydney_f | 48 | 1 |
sydney_f2 | 48 | 1 |
teberda_f | 32 | 1 |
tiao_xi_nan_lu_f | 16 | 1 |
tiao_xi_nan_lu_f2 | 16 | 1 |
tiao_xi_nan_lu_f3 | 16 | 1 |
toolik_nonacidic_f | 32 | 1 |
trebon_basin_biosphere_reserve_f | 8 | 3 |
trebon_basin_biosphere_reserve_f2 | 8 | 3 |
tu_2011_f | 6 | 1 |
tu_2011_f2 | 6 | 1 |
tu_2011_f3 | 6 | 1 |
tu_b_f | 3 | 1 |
tu_b_f2 | 3 | 1 |
tu_b_f3 | 3 | 1 |
ulan_f | 216 | 1 |
ulan_f2 | 216 | 1 |
ulan_f3 | 216 | 1 |
ulan_f4 | 216 | 1 |
ulan_f5 | 216 | 1 |
vikki_f | 30 | 1 |
vikki_f2 | 30 | 1 |
vikki_f3 | 30 | 1 |
winnter_f | 74 | 4 |
xiang_dao_f | 12 | 1 |
xiaojin_b_f | 15 | 1 |
xiaojin_b_f2 | 15 | 1 |
xiaojin_b_f3 | 12 | 1 |
xun_f | 8 | 1 |
xun_f2 | 8 | 1 |
xun_f3 | 8 | 1 |
xun_f4 | 8 | 1 |
yakeshi_f | 6 | 1 |
yakeshi_f2 | 6 | 1 |
zengcheng_f | 8 | 1 |
Plot dots and my box.
df4 %>%
drop_na(myvar) %>%
## give it a nice order (for plotting)
mutate(myvar = factor(myvar, levels = rev(c("anpp", "agb", "root_production", "bgb", "root_shoot_ratio", "n_uptake", "n_inorg")))) %>%
ggplot( aes(x = myvar, y = logr)) +
geom_jitter( color = rgb(0,0,0,0.5),
aes( size = 1/logr_se ),
position = position_jitter(w = 0.2, h = 0)
) +
geom_crossbar( data = df_box %>% drop_na(var),
aes(x = var, y = middle, ymin = ymin, ymax = ymax),
fill = "tomato", color = "black", alpha = 0.6, width = 0.5 ) +
geom_hline( yintercept = 0.0, size = 0.5 ) +
labs(x = "Variable", y = "Log Response Ratio", size = expression(paste("Error"^{-1}))) +
coord_flip() +
labs(title = "MESI data", subtitle = "Response to N-fertilisation")
## Warning: Removed 1 rows containing missing values (geom_point).
Findings:
agb
response (-> STUDENT?)Issues:
for (ivar in use_vars){
print(ivar)
try(metafor::forest(out[[ivar]]$modl))
}
## [1] "anpp"
## [1] "root_production"
## [1] "agb"
## [1] "bgb"
## [1] "root_shoot_ratio"
## [1] "n_inorg"
## [1] "n_uptake"
# purrr::map(as.list(use_vars), ~try(metafor::forest(out[[.]]$modl)))
Plot effect sizes for two different variables against each other, given that data is available for both variables for a given experiment.
## make a wide table with ANPP and BNPP
df4_anpp_bnpp <- df4 %>%
filter(myvar %in% c("anpp", "root_production")) %>%
select(exp, myvar, logr) %>%
tidyr::spread( myvar, logr )
## add standard error
df4_anpp_bnpp <- df4 %>%
filter(myvar %in% c("anpp", "root_production")) %>%
select(exp, myvar, logr_se) %>%
tidyr::spread( myvar, logr_se ) %>%
rename(se_anpp = anpp, se_root_production = root_production) %>%
right_join(df4_anpp_bnpp, by = "exp") %>%
mutate(se = se_anpp * se_root_production)
df4_anpp_bnpp %>%
ggplot(aes(x = anpp, y = root_production, label = exp)) +
geom_point(aes(size = 1/se), color = "tomato") +
xlim(0, 0.8) + ylim(0, 0.8) +
geom_abline(linetype = "dotted") +
ggrepel::geom_text_repel(size = 3, point.padding = 0.5, segment.alpha = 0, color = "grey50") +
labs(x = "Log RR of ANPP", y = "Log RR of root production", size = expression(paste("Error"^{-1}))) +
theme_classic()
## Warning: Removed 54 rows containing missing values (geom_point).
## Warning: Removed 54 rows containing missing values (geom_text_repel).
Issues:
## make a wide table with ANPP and BNPP
df4_agb_bnpp <- df4 %>%
filter(myvar %in% c("agb", "bgb")) %>%
select(exp, myvar, logr) %>%
tidyr::spread( myvar, logr )
## add standard error
df4_agb_bnpp <- df4 %>%
filter(myvar %in% c("agb", "bgb")) %>%
select(exp, myvar, logr_se) %>%
tidyr::spread( myvar, logr_se ) %>%
rename(se_agb = agb, se_bgb = bgb) %>%
right_join(df4_agb_bnpp, by = "exp") %>%
mutate(se = se_agb * se_bgb)
df4_agb_bnpp %>%
ggplot(aes(x = agb, y = bgb, label = exp)) +
geom_point(aes(size = 1/se), color = "tomato") +
xlim(0, 0.6) + ylim(0, 0.6) +
geom_abline(linetype = "dotted") +
ggrepel::geom_text_repel(size = 3, point.padding = 0.5, segment.alpha = 0, color = "grey50") +
labs(x = "Log RR of AGB", y = "Log RR of BGB", size=expression(paste("Error"^{-1}))) +
theme_classic()
## Warning: Removed 282 rows containing missing values (geom_point).
## Warning: Removed 282 rows containing missing values (geom_text_repel).
Issues: