El objetivo es procesar los datos registrados en las UM relevadas en el marco del curso: “Teoría del Muestreo e Inventarios Forestales” dictado por la Facultad de Cs. Forestales de la Universidad Nacional de Misiones, y estimar diferentes variables indicadoras a distintos niveles: individual (árbol), parcela (muestra), lote o estrato.
Cargamos los paquetes necesarios:
library(tidyverse)
library(BIOMASS)
library(vegan)
library(BiodiversityR)
library(tidymodels)
library(MASS)
library(fitdistrplus)Cargamos las bases. Revisar cómo están guardadas y modificar el código según su configuración. “sep” es el separador de valores (columnas) y “dec” el caracter usado para indicar números decimales.
arboles <- read.delim("./bases/arboles.csv", sep = ";", dec = ",")
renovales <- read.delim("./bases/renovales.csv", sep = ";", dec = ",")
sotobosque <- read.delim("./bases/sotobosque.csv", sep = ";", dec = ",")
especies <- read.delim("./bases/especies_listado_completa.csv", sep=";")
matlenioso <- read.delim("./bases/materiallenioso.csv", sep = ";", dec = ",")Miramos un poco la base y el tipo de datos
## Rows: 495
## Columns: 10
## $ PARQUE <chr> "RUMG", "RUMG", "RUMG", "RUMG", "RUMG", "RUMG", "RUMG", "R…
## $ PARCELA <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
## $ N_ARBOL <int> 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, …
## $ PARCELA_CON <chr> "A", "A", "B", "A", "A", "B", "A", "A", "B", "B", "B", "B"…
## $ ESPECIE <chr> "PARRIGID", "PARRIGID", "SIDOBTUS", "OCOPUBER", "PARRIGID"…
## $ ESTADO <int> 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 1, 4, 1, 1, 0, 1, 1, 4, 1, 2…
## $ ALTURA_TOT <dbl> 16, 16, 7, 17, 21, 16, 15, 18, 10, 11, 12, 7, 22, 14, 4, 1…
## $ N_FUSTES <int> 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ DAP <dbl> 24.50986, 38.51550, 19.57606, 56.97747, 29.92113, 17.50704…
## $ COB_LIAN <int> 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## PARQUE PARCELA N_ARBOL PARCELA_CON
## Length:495 Min. : 1.00 Min. : 1.00 Length:495
## Class :character 1st Qu.: 5.00 1st Qu.: 7.00 Class :character
## Mode :character Median :10.00 Median :13.50 Mode :character
## Mean :10.09 Mean :14.85
## 3rd Qu.:15.00 3rd Qu.:21.00
## Max. :20.00 Max. :45.00
## NA's :19
## ESPECIE ESTADO ALTURA_TOT N_FUSTES
## Length:495 Min. :0.000 Min. : 1.50 Min. : 1.000
## Class :character 1st Qu.:1.000 1st Qu.:10.00 1st Qu.: 1.000
## Mode :character Median :1.000 Median :14.00 Median : 1.000
## Mean :1.101 Mean :14.14 Mean : 1.046
## 3rd Qu.:1.000 3rd Qu.:18.00 3rd Qu.: 1.000
## Max. :4.000 Max. :28.00 Max. :11.000
##
## DAP COB_LIAN
## Min. : 4.138 Min. :0.000
## 1st Qu.: 19.417 1st Qu.:0.000
## Median : 24.828 Median :1.000
## Mean : 30.000 Mean :1.578
## 3rd Qu.: 36.128 3rd Qu.:3.000
## Max. :140.375 Max. :4.000
##
El siguiente bloque es para unificar categorías utilizadas
## [1] 23.25
## [1] 1.5
Total arboles = 495, promedio 23.25/parcela, rango 11 a 38 muertos = 30 , promedio 1.5/parcela
Podemos ver la distribución de algunas variables. Para eso nos quedamos solo con árboles DAP > 20 cm
ggplot(arboles, aes(DAP)) +
geom_density() +
facet_grid(.~PARCELA_CON, scales = "free_x") +
theme_bw()ggplot(arboles, aes(x = ESTADO)) +
geom_bar(aes(y = (after_stat(count))/sum(after_stat(count)))) + ylab("Porcentaje") +
theme_bw()ggplot(arboles, aes(x = COB_LIAN)) +
geom_bar(aes(y = 100*(after_stat(count))/sum(after_stat(count)))) + ylab("Porcentaje") +
facet_grid(.~PARCELA_CON) +
theme_bw()Vamos a calcular valor de importancia por especie, riqueza y diversidad por parcela usando los paquetes ‘vegan’ y ‘BiodiversityR’.
arboles %>%
filter(ESTADO > 0) %>% # es lo mismo que hacer ESTADO !=0? por qué?
group_by(PARCELA, PARCELA_CON, ESPECIE) %>%
#calculo las variables para cada subparcela, escalo y después las sumo
summarise(dens = case_when(PARCELA_CON =="A" ~n()*10,
T ~ n()*40),
ab = case_when(PARCELA_CON =="A" ~sum(pi*(DAP/2)^2)/1000,
T ~ sum(pi*(DAP/2)^2)/250)) %>%
group_by(PARCELA, ESPECIE) %>%
summarise(cant = sum(dens),
abt = sum(ab)) -> datos_abund## Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in
## dplyr 1.1.0.
## ℹ Please use `reframe()` instead.
## ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()`
## always returns an ungrouped data frame and adjust accordingly.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `summarise()` has grouped output by 'PARCELA', 'PARCELA_CON', 'ESPECIE'. You
## can override using the `.groups` argument.
## `summarise()` has grouped output by 'PARCELA'. You can override using the
## `.groups` argument.
El valor de importancia (%) es una medida que ponera la frecuencia, densidad y dominancia (área basal) de cada especie.
ivg <- importancevalue(abund,
site = "PARCELA",
species='ESPECIE',
count='cant',
basal='abt',
factor = "")
# algunas operaciones para acomodar los daatos
dfivgd <- as.data.frame(ivg) %>%
rownames_to_column("especie") %>%
arrange(density.percent) %>% #ordeno en base a la densidad
mutate(Especie = as_factor(especie))
ggplot(dfivgd, aes(Especie, density.percent)) +
geom_col(fill = "lightblue") +
theme_bw() +
scale_x_discrete(limits = rev(levels(dfivgd$Especie))) +
xlab("Especie") + ylab("Densidad (árboles/ha)") +
theme(axis.text.x = element_text(angle = 90))dfivg <- as.data.frame(ivg) %>%
rownames_to_column("especie") %>%
arrange(importance.value) %>% #ordeno en base al valor de importancia
mutate(Especie = as_factor(especie))
dfivg %>%
pivot_longer(cols = c(5:7), values_to = "Porcentaje", names_to = "variable")-> dfivg_longggplot(dfivg_long, aes(especie, Porcentaje, group = variable, fill = variable)) +
geom_col() +
scale_x_discrete(limits = rev(levels(dfivg$Especie))) +
theme_bw() +
scale_fill_discrete(name = "Variable", labels = c("Densidad", "Dominancia", "Frecuencia")) +
theme(axis.text.x = element_text(angle = 90))Algunas operaciones para llevar la base a formato de matriz donde cada columna es una especie, las filas corresponden a las parcelas y cada celda indica la densidad de árboles (por ha.).
datos_abund %>%
dplyr::select(-abt) %>%
pivot_wider(names_from = ESPECIE, values_from = cant, values_fill = 0) -> mx_spsPodemos estimar riqueza y diversidad por parcela. Primero creo una base de datos para almacenar las estimaciones
atr_comunitarios$div <- diversity(mx_sps[, 2:68])
atr_comunitarios$riqueza <- specnumber(mx_sps[, 2:68])
atr_comunitariosPara estimar biomasa necesitamos el DAP, altura y densidad de madera de cada árbol. Para eso usamos el paquete ‘BIOMASS’ que es un paquete creado para estimar biomasa aérea en bosques tropicales en base a la ecuacion alométrica propuesta por Chave et al. (2014) y contiene una variedad de funciones muy útiles:
Nosotros vamos a usar el paquete para obtener la densidad de madera de cada especie de la base global de densidad de madera (Chave et al. 2009, Zanne et al. 2009).
La función requiere que haya una columna con el genero y otra la especie. En nuestro caso tenemos los datos cargados directamente con el ‘CODIGO’ de la especie, así que necesitamos armar un diccionario de codigos de especies y preparar el formato:
especies %>%
separate(`NOMBRE.CIENTIFICO`, c("genero", "especie"), sep = " ", remove = F) %>%
dplyr::select(-`NOMBRE.VULGAR`) %>%
rename(ESPECIE = `CODIGO`) -> dicespecies## Warning: Expected 2 pieces. Additional pieces discarded in 94 rows [3, 4, 5, 6, 7, 8, 9,
## 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, ...].
## Warning: Expected 2 pieces. Missing pieces filled with `NA` in 1 rows [77].
Agregamos las columnas “genero” y “especie” a nuestra base:
Ahora si tenemos toda la información en la misma base y podemos correr la función para obtener la densidad de madera:
## The reference dataset contains 16467 wood density values
## Your taxonomic table contains 68 taxa
dm_biomass %>%
dplyr::select(2:4) -> dm_biomass_sub
dfarboles %>%
left_join(dm_biomass_sub, by = c("genero" = "genus", "especie" = "species")) %>%
unique() -> dfarboles## Warning in left_join(., dm_biomass_sub, by = c(genero = "genus", especie = "species")): Detected an unexpected many-to-many relationship between `x` and `y`.
## ℹ Row 1 of `x` matches multiple rows in `y`.
## ℹ Row 1 of `y` matches multiple rows in `x`.
## ℹ If a many-to-many relationship is expected, set `relationship =
## "many-to-many"` to silence this warning.
Y el último paso, estimar biomasa aérea utilizando la ecuación correspondiente. Para árboles, estamos utilizando la ecuación propuesta para bosques tropicales semi-húmedos propuesta por Chave et al. (2005).
dfarboles %>%
mutate(biomasa = case_when(ESPECIE %in% c("SYAROMAN", "EUTEDULI") ~ 6.6666+ (12.826*(DAP^0.5))*log(DAP),
TRUE~ exp(-2.977+log(meanWD*ALTURA_TOT*DAP^2))),
AREA_BASAL_i = pi*((DAP/2)/100)^2) -> dfarboles
dfarbolesHasta acá venimos trabajando a escala o nivel de cada árbol. Lo siguiente es estimar las variables de interés a nivel de parcela y finalmente, hacer las inferencias a nivel de lote o estrato.
Por un lado vamos a separar los registros que corresponden a árboles vivos y árboles muertos en pie. Además, necesitamos llevar todo a la misma unidad (hectárea^-1).
dfarboles %>%
filter(ESTADO != 0) %>%
group_by(PARQUE, PARCELA, PARCELA_CON) %>%
summarise(H_mean = mean(ALTURA_TOT),
AB = sum(AREA_BASAL_i),
dens = n(),
biomasat = sum(biomasa)/1000) %>%
mutate(across(c(AB, dens, biomasat), ~(case_when(PARCELA_CON == "A" ~ .*10,
PARCELA_CON == "B" ~ .*40)))) -> arb_vivos ## `summarise()` has grouped output by 'PARQUE', 'PARCELA'. You can override using
## the `.groups` argument.
dfarboles %>%
filter(ESTADO == 0) %>%
group_by(PARQUE, PARCELA, PARCELA_CON) %>%
summarise(ABm = sum(AREA_BASAL_i),
dens_m = n(),
biomasat_m = sum(biomasa)/1000) %>%
mutate(across(c(ABm, dens_m, biomasat_m), ~(case_when(PARCELA_CON == "A" ~ .*10,
PARCELA_CON == "B" ~ .*40)))) -> arb_muertos## `summarise()` has grouped output by 'PARQUE', 'PARCELA'. You can override using
## the `.groups` argument.
# ponemos todo en una misma base
arb_vivos %>%
left_join(arb_muertos, by = c("PARQUE", "PARCELA", "PARCELA_CON")) %>%
replace(is.na(.), 0) -> estructura_arborea
estructura_arboreaestructura_arborea %>%
pivot_longer(4:10, names_to = "variable", values_to = "valor") %>%
pivot_wider(names_from = PARCELA_CON, values_from = valor, values_fill = 0) %>%
mutate(TOTAL = case_when(variable == "H_mean" ~ A,
TRUE ~ A+B)) %>%
dplyr::select(-c(A, B)) %>%
pivot_wider(names_from = variable, values_from = TOTAL) %>%
mutate(PARCELA = as_factor(PARCELA))-> estructura_arborea_tots
estructura_arborea_totsPodemos visualizar las variables estimadas:
ggplot(estructura_arborea_tots, aes(as_factor(PARCELA), biomasat))+
geom_col() + xlab("Parcela") +
theme_bw()ggplot(estructura_arborea_tots, aes(as_factor(PARCELA), dens))+
geom_col() + xlab("Parcela") +
theme_bw()Por último, le agregamos los atributos comunitarios estimados antes a nuestra base:
La cobertura de estratos se mide a lo largo de una linea transecta que recorre la subparcela A de N a S. Los datos registrados en m lineales hay que llevarlos a %.
sotobosque %>%
arrange(PARCELA) %>%
dplyr::select(1:5) %>%
pivot_longer(3:5, names_to = "Estrato", values_to = "metrosl") %>%
mutate(Porcentaje = metrosl/35.5*100,
PARCELA = as_factor(PARCELA)) %>%
pivot_wider(id_cols = PARCELA, names_from = Estrato, values_from = Porcentaje) -> sotobosque_porc
colnames(sotobosque_porc) <- c("PARCELA", "COB_ARBOREA_7", "COB_ARBOREA_3A7", "COB_BAMBU")
sotobosque_porcAgregamos los datos a la base
Podemos visualizar la cobertura por estrato.
sotobosque_porc %>%
pivot_longer(2:4, names_to = "Estrato", values_to = "Porcentaje") %>%
mutate(Estrato = as_factor(Estrato),
Parcela = as_factor(PARCELA)) -> sotol
ggplot(sotol, aes(Parcela, Porcentaje)) +
geom_col() +
facet_wrap(vars(Estrato), ncol = 1) +
theme_bw()Al igual que con los individuos adultos, con los renovales podemos trabajar a nivel de especie o en general. Se pueden calcular los mismos atributos comunitarios que calculamos, aunque no el valor de importancia porque no tenemos medidas de dominancia.
renovales %>%
mutate(PARCELA = as.numeric(str_sub(PARCELA, start = 5, end = -1L))) %>%
group_by(PARCELA, CLASE, ESPECIE) %>%
summarise(Renovales = sum(CANTIDAD)*200) %>%
pivot_wider(names_from = CLASE, values_from = Renovales, values_fill = 0) %>%
rename(R1 = 3, R2 = 4) %>%
mutate(TOTAL = R1 + R2,
PARCELA = as_factor(PARCELA)) -> renovs_tot_especies## `summarise()` has grouped output by 'PARCELA', 'CLASE'. You can override using
## the `.groups` argument.
renovs_tot_especies %>%
group_by(PARCELA) %>%
summarise(TOTAL = sum(TOTAL),
R1 = sum(R1),
R2 = sum(R2)) %>%
arrange(as.numeric(PARCELA)) -> renovs_tot
renovs_totestructura_arborea_tots %>%
mutate(PARCELA = as_factor(PARCELA)) %>%
left_join(renovs_tot, by = "PARCELA") %>%
replace(is.na(where(is.numeric)), 0) -> estructura_arborea_tots## Warning in is.na(where(is.numeric)): is.na() aplicado a un objeto que no es
## (lista o vector) de tipo 'closure
ggplot(estructura_arborea_tots, aes(as_factor(PARCELA), TOTAL))+
geom_col() + xlab("Parcela") +
theme_bw()
Podemos separar los árboles por clase diamétrica y combinarla con los
registros de renovales para evaluar la distribución de tamaños.
dfarboles %>%
mutate(CLASE_D = as_factor(cut_interval(DAP, length = 10, right = F))) %>%
group_by(PARCELA, CLASE_D) %>%
summarise(Cant = n()) %>%
mutate(Densidad = case_when(CLASE_D == "[10,20)" ~ Cant*40,
T ~ Cant * 10),
PARCELA = as_factor(PARCELA)) %>%
dplyr::select(PARCELA, CLASE_D, Densidad) -> dfclasesd## `summarise()` has grouped output by 'PARCELA'. You can override using the
## `.groups` argument.
renovs_tot %>%
dplyr::select(1:2) %>%
rename(Densidad = TOTAL) %>%
mutate(CLASE_D = "[0,10)") %>%
dplyr::select(PARCELA, CLASE_D, Densidad) %>%
bind_rows(dfclasesd) %>%
arrange(PARCELA) %>%
mutate(CLASE_D = as_factor(CLASE_D))-> dfclasesd
dfclasesdEl muestreo de material leñoso caído se utiliza para estimar la biomasa muerta en descomposición y como indicador de las emisiones de C que se producirán.
Primero calculamos la densidad de madera promedio para utilizar de referencia:
## [1] 0.604998
Necesitamos estimar cómo decae el C almacenado en la madera a medida que se descompone. A campo, el material leñoso es clasificado en 4 categorías según el grado de descomposición. Vamos a suponer:
| Categoria | MO remanente (%) |
|---|---|
| 1 | 100 |
| 2 | 90 |
| 3 | 75 |
| 4 | 50 |
Con esto estimamos la necromasa caída:
matlenioso %>%
mutate(PARCELA = as_factor(str_sub(Parcela, start = 5, end = -1L)),
DM = case_when(Estado == 1 ~ 0.605,
Estado == 2 ~ 0.605*0.9,
Estado == 3 ~ 0.605*0.75,
Estado == 4 ~ 0.605*0.5),
masa_i = pi*(Diametro..cm./2)^2*DM) %>%
group_by(PARCELA) %>%
summarise(Necromasa = (sum(masa_i)/35*100)*(10^-2)*0.1) -> necromasa_caida #en tn/ha y esto lo usamos en combinación con los árboles muertos en pie para estimar la necromasa total
estructura_arborea_tots %>%
left_join(necromasa_caida, by="PARCELA") %>%
mutate(necromasat = replace_na(biomasat_m + Necromasa, 0)) -> estructura_arborea_totsy podemos visualizar:
ggplot(estructura_arborea_tots, aes(as_factor(PARCELA), necromasat))+
geom_col() + xlab("Parcela") +
theme_bw()El último paso es hacer inferencias a partir de las estimaciones muestrales. Vamos a calcular la media (+/- ES) de biomasa, necromasa, área basal y densidad de árboles de la Reserva.
estructura_arborea_tots %>%
dplyr::select(AB, dens, biomasat, necromasat) %>%
pivot_longer(AB:necromasat, names_to = "variable", values_to = "valor") %>%
group_by(variable) %>%
summarise(media = mean(valor),
es = sd(valor)/sqrt(19))## Adding missing grouping variables: `PARQUE`, `PARCELA`
También podemos estudiar la regeneración a escala de la reserva. Primero, promediamos la densidad de árboles por clase diamétrica:
orden <- c("[0,10)", "[10,20)", "[20,30)","[30,40)", "[40,50)", "[50,60)", "[60,70)","[70,80)", "[80,90)", "[90,100)", "[100,110)", "[110,120)",">=120")dfclasesd %>%
group_by(CLASE_D) %>%
summarise(Densm = mean(Densidad)) -> dfclasesm
dfclasesm$CLASE_D = factor(dfclasesm$CLASE_D, levels = orden)Vemos cómo quedó:
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_col()`).
Podemos estimar los parámetros característicos de la distribución de Weibull usando los paquetes ‘MASS’ y ‘fitdistrplus’
## Fitting of the distribution ' weibull ' by maximum likelihood
## Parameters:
## estimate Std. Error
## shape 0.4945837 0.09242295
## scale 73.5073431 44.00866443