knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
As noted in the introductory vignette, there are many reasons why greenhouse gas concentration observations might not be well fit by a linear model: diffusion effects, saturation, mixing problems, etc.
The fluxfinder
package provides extensive outputs based on linear
model fits, and a few QA/QC indicators based on a polynomial model, but there
are cases where we might want to take advantage of more sophisticated
model-fitting routines.
library(fluxfinder) # Load the data # Data from a LI-7810 f <- system.file("extdata/TG10-01087-curvature.data", package = "fluxfinder") dat <- ffi_read_LI7810(f) # Fit a linear flux and QA/QC it flux <- ffi_compute_fluxes(dat, group_column = NULL, time_column = "TIMESTAMP", gas_column = "CO2") print(flux$lin_flux.estimate) print(flux$lin_r.squared) print(flux$poly_r.squared) print(flux$HM81_flux.estimate)
There's a fairly large jump from the R2 of the linear
model (0.93) to that of a polynomial (0.99+), and the flux computed by the
Hutchinson and Mosier (1981) nonlinear
approach is numeric (i.e., non-NA
).
This implies nonlinearity in our data:
library(ggplot2) dat$SECONDS <- dat$SECONDS-min(dat$SECONDS) ggplot(dat, aes(SECONDS, CO2)) + geom_point() + # naive linear model geom_smooth(method = "lm", formula = 'y ~ x') + # HM1981 flux line geom_abline(slope = flux$HM81_flux.estimate, intercept = min(dat$CO2), linetype = 2)
There's definitely a problem! Depending on what we think is happening here,
one option would be to change the observation length so that the flux is
computed based on only the first ~75 seconds, which looks linear. A second
option would be to use the flux_HM1981
field as our flux.
A third option would be fit more sophisticated model(s).
The gasfluxes package also provides routines to calculate greenhouse gas fluxes from chamber measurements, and includes code to fit the HMR model as well as several model-selection routines.
library(gasfluxes) # Add some columns that gasfluxes expects dat$ID <- "test" dat$V <- 0.1 dat$A <- 0.16 gasfluxes(dat, .times = "SECONDS", .C = "CO2", plot = FALSE)
gasfluxes
will compute on multiple groups (measurements) via its .id
parameter, but we can also use use fluxfinder::ffi_compute_fluxes()
to
handle the grouping and let it call gasfluxes
:
# Define a small wrapper function to put things into the format # that gasfluxes expects f <- function(time, conc) { d <- data.frame(time = time, C = conc, ID = 1, A = 1, V = 1) gasfluxes(d, plot = FALSE) } ffi_compute_fluxes(dat, NULL, "SECONDS", "CO2", fit_function = f)
This vignette covered how to integrate gasfluxes
with fluxfinder
, if
you want to take advantage of the former package's HMR or NDFE routines.
More information on these models can be found in:
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.