library(readxl)
library(lubridate)
library(tidyverse)
library(plotly)
library(stargazer)
library(Metrics)
AIM : To compare HOBO (lux) and LiCOR (PAR) data. Found out conversion rate between LUX and PAR. Explore potential biaises of relationship with Depth or HOBO sensors. Compare linear and non linear regression following Long et al. (2012).
Document Note : The maps, plots and app within this document are interactive so make sure you give them a play like zooming in and out in the maps but also on the plots. Clicking on the legend allows to only select and display the time series needed.
hobo_licor <- read_excel('Kaik_lux_light_2021.xlsx')
## Plot Hobo vs PAR - No distinction of Depth, Time (hour), Site
p <- ggplot(hobo_licor,aes(x=Lux,y=PAR)) +
geom_point() +
geom_smooth(formula = y ~ x, se=T, method = 'lm') +
theme_light() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=20))
ggplotly(p)
Figure 1 - PAR vs LUX and linear regression.
\(R^2\) of linear fit:
lm_fit <- lm(PAR ~ Lux, data = hobo_licor) #%>% tidy() %>% kable()
#summary(lm_fit)#$r.squared
#lm(Kd_MW ~ Kd_NN, data = nn_mw_idw_tb) %>% kable()
stargazer(lm_fit,title="Regression Results",type = "text", style = 'default')#"html"
##
## Regression Results
## ===============================================
## Dependent variable:
## ---------------------------
## PAR
## -----------------------------------------------
## Lux 0.028***
## (0.001)
##
## Constant 68.408***
## (3.031)
##
## -----------------------------------------------
## Observations 516
## R2 0.817
## Adjusted R2 0.817
## Residual Std. Error 34.468 (df = 514)
## F Statistic 2,297.848*** (df = 1; 514)
## ===============================================
## Note: *p<0.1; **p<0.05; ***p<0.01
\(R^2\) = .817, probably not too bad but definitely some variability. Due to what? Sensors? Depth?
\(PAR = 0.028*LUX + 68.408\)
p <- ggplot(hobo_licor,aes(x=Lux,y=PAR,col=Hobo,group=Hobo)) +
geom_point() +
geom_smooth(formula = y ~ x, se=T, method = 'lm') +
theme_light() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=20))
ggplotly(p)
Figure 2 - PAR vs LUX and effect of sensor type on linear regression.
\(R^2\) of linear fit:
lm_fit_sensor40 <- hobo_licor %>%
dplyr::filter(Hobo == '40') %>%
lm(PAR ~ Lux, data = .)
lm_fit_sensorwbn2 <- hobo_licor %>%
dplyr::filter(Hobo == 'WBN 2') %>%
lm(PAR ~ Lux, data = .)
lm_fit_sensor5 <- hobo_licor %>%
dplyr::filter(Hobo == '5') %>%
lm(PAR ~ Lux, data = .)
lm_fit_sensor21 <- hobo_licor %>%
dplyr::filter(Hobo == '21') %>%
lm(PAR ~ Lux, data = .)
stargazer(lm_fit_sensor21,lm_fit_sensor40,lm_fit_sensor5,lm_fit_sensorwbn2, title="Regression Results for Sensors 21 (1), 40 (2), 5 (3) and WBN 2 (4).",type = "text", style = 'default')#"html"
##
## Regression Results for Sensors 21 (1), 40 (2), 5 (3) and WBN 2 (4).
## ============================================================================
## Dependent variable:
## ---------------------------------------------
## PAR
## (1) (2) (3) (4)
## ----------------------------------------------------------------------------
## Lux 0.028*** 0.025*** 0.033*** 0.031***
## (0.001) (0.001) (0.001) (0.001)
##
## Constant 62.953*** 66.663*** 60.628*** 64.244***
## (5.160) (6.538) (4.723) (5.813)
##
## ----------------------------------------------------------------------------
## Observations 129 129 129 129
## R2 0.871 0.798 0.893 0.839
## Adjusted R2 0.870 0.796 0.892 0.837
## Residual Std. Error (df = 127) 29.106 36.459 26.536 32.564
## F Statistic (df = 1; 127) 858.827*** 501.275*** 1,058.984*** 660.555***
## ============================================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
Variability in \(R^2\): .798 for sensor 40 vs .892 for sensor 5. Also Sensor 40 “under-estimates” PAR the most and sensor 5 “over-estimates” PAR the most.
p <- ggplot(hobo_licor,aes(x=Lux,y=PAR)) +
facet_wrap(~Depth, scales = 'free') +
geom_point(aes(col=Sample)) +
geom_smooth(formula = y ~ x, se=T, method = 'lm') +
theme_light() +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=12))
ggplotly(p)
Figure 3 - PAR vs LUX and effect of depth on linear regression.
\(R^2\) of linear fit:
lm_fit_depth1 <- hobo_licor %>%
dplyr::filter(Depth == '1') %>%
lm(PAR ~ Lux, data = .)
lm_fit_depth2 <- hobo_licor %>%
dplyr::filter(Depth == '2') %>%
lm(PAR ~ Lux, data = .)
lm_fit_depth3 <- hobo_licor %>%
dplyr::filter(Depth == '3') %>%
lm(PAR ~ Lux, data = .)
lm_fit_depth4 <- hobo_licor %>%
dplyr::filter(Depth == '4') %>%
lm(PAR ~ Lux, data = .)
lm_fit_depth5 <- hobo_licor %>%
dplyr::filter(Depth == '5') %>%
lm(PAR ~ Lux, data = .)
lm_fit_depthascent <- hobo_licor %>%
dplyr::filter(Depth == 'ascent') %>%
lm(PAR ~ Lux, data = .)
stargazer(lm_fit_depth1,lm_fit_depth2,lm_fit_depth3,lm_fit_depth4,lm_fit_depth5,lm_fit_depthascent, title="Regression Results for Depth 1m (1), 2m (2), 3m (3), 4m (4), 5m (5) and ascent (6).",type = "text", style = 'default')#"html"
##
## Regression Results for Depth 1m (1), 2m (2), 3m (3), 4m (4), 5m (5) and ascent (6).
## ===================================================================================================================================================================
## Dependent variable:
## -----------------------------------------------------------------------------------------------------------------------------------------------
## PAR
## (1) (2) (3) (4) (5) (6)
## -------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Lux 0.023*** 0.022*** 0.030*** 0.024*** 0.026*** 0.034***
## (0.002) (0.002) (0.002) (0.002) (0.001) (0.007)
##
## Constant 123.420*** 114.616*** 67.601*** 81.741*** 60.567*** 85.694***
## (11.897) (13.775) (11.400) (6.958) (3.003) (26.357)
##
## -------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Observations 84 60 48 48 244 32
## R2 0.736 0.730 0.794 0.808 0.771 0.427
## Adjusted R2 0.733 0.725 0.789 0.804 0.770 0.408
## Residual Std. Error 42.998 (df = 82) 45.064 (df = 58) 23.672 (df = 46) 14.624 (df = 46) 14.290 (df = 242) 51.643 (df = 30)
## F Statistic 228.329*** (df = 1; 82) 156.511*** (df = 1; 58) 177.102*** (df = 1; 46) 194.013*** (df = 1; 46) 813.218*** (df = 1; 242) 22.326*** (df = 1; 30)
## ===================================================================================================================================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
Highest \(R^2\) at depth 4m, lowest for ascent (makes sense). Presence of “clusters” indicative of 2 different time of the day (morning vs afternoon).
p <- ggplot(hobo_licor,aes(x=Lux,y=PAR,color=Hobo,group=Hobo)) +
facet_wrap(~Depth, scales = 'free') +
geom_point() +
geom_smooth(formula = y ~ x, se=T, method = 'lm') +
theme_light() +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=12),
strip.text = element_text(size=12))
ggplotly(p)
Figure 4 - PAR vs LUX and effect of sensor type and depth on linear regression.
Limitation:
In Long et al. (2012),they assume a saturating behavior of PAR values (LiCOR) for high LUX values (from HOBO). They use the equation: \(PAR_{LiCOR} = A_1 \exp(-HOBO/t_1) + y_0\).
model_long <- nls(PAR ~ A1*exp(-Lux/t1) + y0, data=hobo_licor, start = list(A1 = -20000, t1 = 20000, y0 = 2000))
summary(model_long)
##
## Formula: PAR ~ A1 * exp(-Lux/t1) + y0
##
## Parameters:
## Estimate Std. Error t value Pr(>|t|)
## A1 -592.66 48.75 -12.156 < 2e-16 ***
## t1 12840.07 1907.28 6.732 4.49e-11 ***
## y0 618.75 54.58 11.337 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 32.75 on 513 degrees of freedom
##
## Number of iterations to convergence: 6
## Achieved convergence tolerance: 2.799e-06
Coefficients are compared to Long et al. (2012):
Quite lower than Long et al. (2012), not same range of LUX might be why + data quantity.
p <- ggplot() +
geom_point(data=hobo_licor,aes(x=Lux,y=PAR)) +
geom_line(data=hobo_licor,aes(x=Lux,y=predict(model_long)),col='red',size=1) +
geom_line(data=hobo_licor,aes(x=Lux,y=predict(lm_fit)),col='blue',size=1)
ggplotly(p)
Figure 5 - PAR vs LUX, linear regression (blue) and exponential regression following Long et al. (2012) (red).
Let’s compare the RMSE between models:
paste0('Long Expo Model RMSE =',rmse(hobo_licor$PAR,predict(model_long)))
## [1] "Long Expo Model RMSE =32.652806338231"
paste0('Linear Model RMSE =',rmse(hobo_licor$PAR,predict(lm_fit)))
## [1] "Linear Model RMSE =34.4007905909135"
And let’s compare the AIC between models:
AIC(model_long,lm_fit)
## df AIC
## model_long 4 5069.825
## lm_fit 3 5121.643
The exponential model seems better. But we porbably need more data at higher LUX.