Evolving notes, images and sounds by Luis Apiolaza

Category: teaching (Page 4 of 14)

Some love for Base R. Part 4

Following on parts 1, 2 & 3—yes, a series—we arrive to part 4 revisiting Base R. See part 1 for the rationale, in case you’re wondering Whyyyy?

A typical question going back to Base from the tidyverse: How do I join datasets? What do I use instead of bind_rows() and bind_cols()? Easy, rbind() and cbind(), yes, r for rows and c for cols, because base is concise.

By rows

If we have a couple of data frames with the same variables (columns), then using rbind() binds/glues/stitches the data frames one after the other.

example_df1 <- data.frame(record = 1:24,
                          treatment = rep(LETTERS[1:3], each = 8))

example_df2 <- data.frame(record = 25:48,
                          treatment = rep(LETTERS[4:6], each = 8))

example_df3 <- data.frame(record = 49:72)

# This one works
example_bound <- rbind(example_df1, example_df2)

# This one doesn't as they don't have the same variables
example_bound <- rbind(example_df1, example_df3)

# If we redefine the data frame we can join more than two data frames
example_df3 <- data.frame(record = 49:72,
                          treatment = rep(LETTERS[7:9], each = 8))

example_bound <- rbind(example_df1, example_df2, example_df3)

Of course we can use pipes too:

example_df1 |> rbind(example_df2) -> example_bound2

By columns

If we have a couple of data frames with the same number of rows (cases), then using cbind() binds/glues/stitches the data frames side by side.

example_df4 <- data.frame(record = 1:24,
                          treat1 = rep(LETTERS[1:3], each = 8))

example_df5 <- data.frame(treat2 = rep(LETTERS[4:5], 12),
                          meas = rnorm(24))

example_cbound <- cbind(example_df4, example_df5)
example_cbound

   record treat1 treat2       meas
1       1      A      D -2.1158479
2       2      A      E  0.7784022
3       3      A      D -0.0112054
4       4      A      E -0.1986594
...

When you are working with data frames you get pretty much what you’d expect in dplyr. However, if you are not working with data frames but, instead, you’re dealing with vectors you end up with matrices, in which all elements have the same type. Coercing different types may produce unexpected results

# Binding columns
x <- 1:26
y <- sqrt(x)

example_1 <- cbind(x, y)

# What do we get?
is.matrix(example_1)
[1] TRUE

example_1
       x        y
 [1,]  1 1.000000
 [2,]  2 1.414214
 [3,]  3 1.732051
 [4,]  4 2.000000
 ...

# Perhaps unexpected result. Variable x
# was coerced to character
example_2 <- cbind(x, letters)
example_2
      x    letters
 [1,] "1"  "a"    
 [2,] "2"  "b"    
 [3,] "3"  "c"    
 [4,] "4"  "d"  
 ...

By one or more indices

When you have data frames with one or more variables “in common” the function to use is merge(), which may work like left_join() and right_join() in dplyr.

merge(x, y, by =)
# which you can read as
merge(left, right, by = )

Think of x as left and y as right. Using all.x = TRUE extra rows will be added to the output, one for each row in x that has no matching row in y. Using all.y = TRUE extra rows will be added to the output, one for each row in y that has no matching row in x.

As an example, I have two data frames with a tree id (ids) and a derived variable (first tree ring to achieve a technical threshold for microfibril angle and modulus of elasticity). I would like to join them by ids:

head(firstmfa)
    ids assess
1 DM001      3
2 DM002      5
3 DM003      4
4 DM004      6
5 DM005      5
6 DM006      7

head(firstmoe)
    ids ring
1 DM001    8
2 DM002    8
3 DM003    8
4 DM004    8
5 DM005    9
6 DM006   12

# Merging keeping all observations
gendata <- merge(firstmfa, firstmoe, by = 'ids', all = TRUE)

Another example using more than one joining variable. Actual wood density (in kg/m3) and microfibril angle (in degrees) assessments per tree ring, joined by tree code and ring number

> head(densdataT)
    ids ring density
1 DM001    1      NA
2 DM001    2      NA
3 DM001    3  327.96
4 DM001    4  325.37
5 DM001    5  336.59
6 DM001    6  360.82
...

> head(mfadataT)
    ids ring   mfa
1 DM001    1    NA
2 DM001    2    NA
3 DM001    3 31.93
4 DM001    4 31.70
5 DM001    5 33.21
6 DM001    6 27.98

assess <- merge(densdataT, mfadataT, by = c('tree', 'ring'), all = TRUE)

Sense-checking data

Over the birdsite dumpster fire. Emily Harvey was asking:

do you know of any good guidelines/advice for what one should do to sense check and make sure they understand any data before using it?

I replied the following:

Typically, I might be very familiar with the type of data and its variables (if it is one of my trials) or chat/email multiple times with the owner of the dataset(s) so I can check that:

  • units and recorded values match. If units are mm, for example, the magnitudes should make sense in mm.
  • the order of assessments and experimental/sampling design match: people often get lost in trials or when doing data collection, recording the wrong sampling unit codes.
  • dates are OK. I prefer 2023-04-07; anyway, this is often a problem when dealing with Excel data.
  • if we are using environmental data that it matches my expectation about the site. Have found a few weather station problems doing that, where rainfall was too low (because there was a sensor failure).
  • the relationship between variables are OK. Example of problems: tall and too skinny trees, fat and short ones, suspicious (unless broken, etc), diameter under bark smaller than over bark, big etc.
  • levels of factor match planned levels (typically there are spelling mistakes and there are more levels). Same issue with locality names.
  • map coverage/orientation is OK (sometimes maps are sideways). Am I using the right projection?
  • joins retain the appropriate number of rows (I mean table joins using merge or left_join in R, etc).
  • Missing values! Are NA coded correctly or with zeros, negative numbers? Are they “random”?
  • If longitudinal data: are older observations larger (or do we get shrinking trees?)
  • etc

Of course these questions are dataset dependent and need to be adapted to each separate situation. Finally: Do results make any sense?

Some love for Base R. Part 3

It seems a few people have found useful the reminders of base-R functionality covered in “Some love for Base R” Part 1 and Part 2. So I will keep on mentioning a few bits and pieces that you may find handy when going back to Base or even visiting it for the first time.

A reminder: the fictional setting is that you are revisiting legacy code or developing new code under strong constraints: minimal use of packages. The latter could be because you are using webR or you’re keen on having few dependencies. I am assuming R 4.1 when mentioning native pipes, but not the existence of the _ placeholder yet.

In this post I play a little with variable names. None of this would be “production code”, but it would work fine in your analyses. I have similar code (except without pipes) that is almost 20 years old and still running.

A rose by any other name would smell as sweet

William Shakespeare

Changing variable names, renaming, does not work quite like in the tidyverse, in which it can be one more step in a list of transformations with rename(). In base R we rely on the names() function, which is used for both for listing the names of an object and changing them. Usually people would either change all names, providing a vector with names, or replacing one or more names by referring to their position, as in:

names(warpbreaks)
#[1] "breaks"  "wool"    "tension"

names(warpbreaks) <- c("bre", "woo", "ten")
names(warpbreaks)
#[1] "bre" "woo" "ten"

names(warpbreaks)[3] <- "tension"
names(warpbreaks)
#[1] "bre"     "woo"     "tension"

names(warpbreaks)[1:2] <- c("breaks", "wool")
names(warpbreaks)
#[1] "breaks"  "wool"    "tension"

One problem is relying on the position of the variable, which may change with different datasets. One option—although a bit wordy—is to use a regular expression to rename a specific variable with the base sub() function:

# General use
# names(data_frame) <- sub("old_name", "new_name", names(data_frame))

names(warpbreaks) <- sub("wool", "woolly", names(warpbreaks))
names(warpbreaks)
#[1] "breaks"  "woolly"  "tension"

Inside sub() we get a list of all the names for the data frame, look for the one that matches “wool” and replace it by “woolly”.

Cleaning names

A typical problem when receiving datasets is that the authors followed weird naming conventions or, more likely, no convention at all. There are shouting ALLCAPS, names separated by dots, or by spaces, or whatever. I usually work with lowercase names separated by underscores if more than one word. The easiest way to convert names is using janitor‘s clean_names() function.

Our data set’s names could look like this:

names(bos)
#[1] "BLOCK_NO"  "TREE_NO"   "FAM_CODE"  "age core"  "site.code"

I could write a bare bones clean names function in base (covering most of my cleaning needs) using the following code:

names(data_frame) |> tolower() |> {\(x) gsub("[\\. ]", "_", x)}()

For a data frame:

1. get names for the data frame names(data_frame)

2. pass them to the next function |> (using native pipe)

3. convert names to lowercase tolower()

4. replace dots and spaces with underscore using regular expression gsub()

The Klingonian part is a lambda function wrapped by { }() so it works with the native pipe and it is the same as {function(x) gsub("[\\. ]", "_", x)}(). One could perfectly write the code without pipes and using less Klingon.

Applying the function we’d get:

names(bos) |> tolower() |> {\(x) gsub("[\\. ]", "_", x)}()
#[1] "block_no"  "tree_no"   "fam_code"  "age_core"  "site_code"

Of course you’d need to assign the names, so they overwrite the existing ones. Easiest way would be to add -> names(bos) at the end of the line. A right-side assign (wink).

names(bos) |> tolower() |> {\(x) gsub("[\\. ]", "_", x)}() -> names(bos)

Entrevista: información de fondo

El jueves pasado, miércoles en Chile, grabamos una entrevista con Gabriel León. Espero haber dejado claro que era mi opinión personal, en el sentido que no representa una posición institucional, pero también en el sentido de que está informada por 30 años de mi ejercicio profesional.

Gabriel me contactó partiendo de ver algunos de mis intercambios en Twitter acerca de incendios forestales y el sector forestal en general. Mi posición parte de que la discusión en general ha sido tremendamente improductiva y muestra mucho desconocimiento, se ha permitido ignorar el trabajo de muchos investigadores y le falta imaginación de otros futuros posibles. Al mismo tiempo, algunas (o varias) de las cosas que digo pueden sonar extrañas, así que he puesto algunas notas con referencias que son en su mayoría de libre acceso.

A pesar de la abundancia de todólogos en la discusión pública en Chile, nadie puede saber de todo, incluso acerca de ecosistemas forestales, tanto de bosque nativo como de plantaciones (y sí, las plantaciones forestales son ecosistemas). Ese no saber de todo me incluye y en mi participación en el discurso público hago uso de mucha investigación producida por colegas.

Voy a ir agregando a este post cuando tenga un poco de tiempo, porque ya empezamos las clases el 20 de febrero en Nueva Zelanda.

Sustitución ¿De qué?

Cualquier discusión acerca de procesos de cambios de uso de la tierra y de cobertura vegetacional (LULC por sus siglas en inglés Land Use Land Cover change) debería reconocer que los cambios del uso de la tierra en Chile no son un proceso reciente, exclusivo del período post-DL701. Prácticamente toda la tierra usada actualmente por los sectores agrícola, ganadero y forestal antes estaba cubierta por alguno de los tipos forestales nativos. ¿Viñedos, frutales, trigo, vacas lecheras, pinos, etc? Sí, todos.

Se estima que para el primer centenario de Chile, en 1910, ya se había perdido más de la mitad del área original de bosque nativo. El mayor empuje deforestador vino con la política de colonización por europeos en la segunda mitad del siglo 19. ¿Pero se han detenido ha pensar alguna vez el nivel de consumo de madera para durmientes de ferrocarriles? ¿o el nivel de deforestación para la producción de trigo en “el granero de Chile”?

En general, las plantaciones forestales han seguido este proceso de sustitución (llamémoslo tipo A):

Bosque Nativo -> Agricultura-Ganadería (con pérdida de productividad) -> Plantación Forestal

Sin embargo, hay casos en que se ha dado este proceso de sustitución (con el que estoy en completo desacuerdo, digamos que es tipo B):

Bosque Nativo -> Plantación Forestal

Justo mientras buscaba referencias asequibles para la discusión de cambios en políticas de conservación en Chile, encontré un libro que leí este fin de semana: Medio siglo de políticas públicas de conservación de la naturaleza en Chile (PDF) de Araya. Estudia una pregunta interesante ¿estamos mejor el bosque hoy o medio siglo atrás? donde medio siglo en realidad va atrás hasta antes del gobierno de Frei en los años sesenta. Necesita un poco de edición, pero entrega mucha información útil y contexto para entender la discusión forestal hoy.

La sustitución y degradación del bosque nativo continuó en el siglo 20, con otro punto álgido en los años cuarenta a sesenta producto de los incendios en la colonización de Aysén, para “limpiar” y crear terrenos agrícolas. El 80% de las pérdidas de montes (bosques achaparrados) entre 1944 y 1994 ocurrieron de Chiloé al sur (página 32 en libro de Araya), bastante antes de la creación del DL701 en octubre de 1974 (comienzo de la dictadura).

Un artículo bien legible resumiendo los cambios de los últimos 50 años es Native forest loss in the Chilean biodiversity hotspot: revealing the evidence publicado por Miranda, Altamirano, Cayuela, Lara y González en 2016.

Lamentablemente este artículo no es de acceso libre, así que si no tienes acceso a una biblioteca con subscripción, lo puedes leer usando sci-hub.ru. No digo que es legal, pero es una posibilidad.

Una buena parte de las plantaciones, pero no todas, fueron cambios de uso Tipo A: ex-terrenos agrícolas degradados por malas prácticas y en zonas de productividad marginal. El artículo de Miranda y colaboradores (2016) tiene un gráfico muy interesante, mostrando la pérdida neta de bosque nativo de 1970-1990, 1990-2000 y 2000-2010. ¿Cuáles son las causas de esta pérdida? Los autores indican que “nuestros resultados muestran que hay una gran variabilidad in la pérdida de bosque nativo, en términos de intensidad y las causas aproximadas de dicha pérdida” (our results show that there is great variability in native forest loss, in terms of intensity and the proximate causes of loss). Al mismo tiempo, ellos indican que hay evidencia de que parte de este remplazo fue directamente a plantaciones forestales.

Pérdida neta y porcentual de cobertura de bosque nativo entre 1970 y 2010.

Uno de los cambios netos más grandes de bosque nativo ha sucedido en un área interesante: Araucanía-Wallmapu. Sería interesante ver cuál es el nivel de correlación entre cambio de uso de la tierra y conflicto.

DL701 y legislación asociada

Las plantaciones forestales de pino y eucalipto no comenzaron con el DL701 de 1974, cuando ya existía más de medio millón de hectáreas. Tampoco es el primer caso de incentivo a las plantaciones en Chile. Por ejemplo, la ley de bosques del año 1931 que establecía exenciones tributarias, protección ambiental y multas. La protección y multas nunca se aplicaron. A todo esto, ¿de dónde saco el medio millón de hectáreas?

El Anuario Forestal 2022 del Instituto Forestal (INFOR) tiene el cuadro 2.7 (página 31) que muestra aproximadamente 712 mil ha de plantaciones (641 mil son pino) a fines de 1978. El informe DL701 Cuarenta años de incentivos a la forestación 1975-2015 producido por CONAF en 2016 muestra en la tabla 2 (página 12) 85 mil ha de plantaciones bonificadas en los años 1976-1978 inclusive. 712 mil – 85 mil = 627 mil ha antes de 1975, que redondeo a “más de medio millón” porque es a- conservador y b- fácil de recordar.

Como referencia, una hectárea (abreviado ha) son 100 m x 100 m (10.000 m2) y una cancha oficial de fútbol es de 105 m x 68 m (7.140 m2). El césped del Estadio Nacional en Santiago, incluyendo cancha y área que la rodea es 120 m x 90 m (10.800 m2). Nada que ver, pero no tenía idea de que el estadio ahora se llama “Estadio Nacional Julio Martínez Prádanos”.

La composición de los beneficiarios del subsidio cambia con tiempo. Así en el primer período (1975-1995) la recepción de subsidios es dominada por grandes empresas y propietarios. La ley 19.561 de 1998 modifica el DL701, concentrando los subsidios en pequeños y medianos propietarios e incorporando incentivos para la recuperación de suelos degradados. Los gráficos muestran el cambio de orientación, con mayor participación de pequeños propietarios y restauración de tierras degradadas.

Evolución en las áreas bonificadas (hectáreas en el eje Y, año en el eje X). Consorcios forestales y medianos propietarios dominan el primer período, pequeños y medianos propietarios dominan el segundo período (Fuente: informe de CONAF citado anteriormente, página 24).
Evolución de los montos modificados en miles de dólares (es decir 30.000 es 30 millones, por ejemplo) por tipo de propietario. Inicialmente los montos son dominados por consorcios forestales y medianos propietarios; luego los montos son dominados por los pequeños y medianos propietarios.

En 2008 aparece la Ley 20.283 de Recuperación del Bosque Nativo y Fomento Forestal que considera bonificaciones para la conservación, recuperación y manejo de bosques nativos.

Biodiversidad

Hay una preconcepción bastante común con respecto al nivel de biodiversidad de las plantaciones. incluyendo el uso del término desierto biológico. Sin embargo, si uno visita plantaciones es común ver otros organismos además de las especies plantadas, tanto de flora (más de 85 especies, mayoritariamente nativas) y fauna (invertebrados, aves, mamíferos).

Una revisión bastante completa del nivel de biodiversidad en plantaciones forestales, con énfasis en Chile, es Biodiversity in Monterrey Pine Plantations por Estades, Grez y Simonetti.

Hay evidencia de que el nivel de biodiversidad en una plantación está relacionado con el uso anterior del sitio; por ejemplo en el artículo Effect of Land Use History on Biodiversity of Pine Plantations de Uribe, García y Estades. Si el sitio tenía bajo nivel de biodiversidad antes de plantar (por ejemplo un terreno agrícola con una especie) la plantación forestal también tendría baja biodiversidad.

¿Hay vegetación más inflamable que otra?

Respuesta corta: sí. Hay varios estudios quemando vegetación (muchas veces en una parrilla) para ver si distintas especies y mezclas de especies se comportan de manera diferente frente a incendios. Un ejemplo sería Shoot-Level Flammability of Species Mixtures is Driven by the Most Flammable Species: Implications for Vegetation-Fire Feedbacks Favouring Invasive Species (2017) de Wyse y colaboradores que se hizo en Nueva Zelanda. A todo esto, partes de la vegetación nativa de Chile y NZ son muy similares, así como también las especies exóticas usadas en plantaciones. Y Wyse tiene su oficina una pocas puertas de la mía; el mundo es chico.

Agua

El otro día leí algo totalmente tirado de las mechas: “como pinos y eucaliptos no se riegan, extraen agua lluvia desde el primer metro de profundidad de suelo y, por lo tanto, no compiten con los pozos o napas subterráneas”. O algo por el estilo, entre broma mala y argumento de jardín infantil, típico de todólogo. En realidad el ciclo del agua es más complejo que el primer metro del suelo.

Ciclo hídrico de suelo desnudo (izquierda) y cubierto con vegetación (derecha). Es de notar que el rendimiento hídrico (Q) depende de varios factores. La vegetación reduce la escorrentía superficial (runoff), aumenta la infiltración, e incremental la evapotranspiración. Todo eso afecta la producción de agua en la cuenca.

La presencia de vegetación reduce el rendimiento hídrico de una cuenca, o sea queda menos agua para otros usos. El bosque nativo reduce la cantidad de agua con respecto a un pastizal; una plantación de alta productividad va a tender a usar más agua que un bosque nativo. Pero, el efecto sobre el rendimiento de agua también depende del nivel de aridez de la cuenca y de la proporción de árboles que la cubran. Por ejemplo, en Effects of Eucalyptus plantations on streamflow in Brazil: Moving beyond the water use debate (2019) de Barros Feraz y colaboradores señalan que hay un 40% de plantaciones de eucaliptos (en áreas de aridez más elevada) que requieren ajustes a su sistema de manejo. Ellos también sugieren que se necesita planificación a nivel de cuenca para equilibrar el uso del agua. Pueden necesitar sci-hub para leer esta referencia.

Otro ejemplo de efectos sobre el agua lo dan Fahey y Jackson en Hydrological impacts of converting native forests and grasslands to pine plantations, South Island, New Zealand (1997) en vegetación de Nueva Zelanda que es similar a la chilena, usando pino radiata.

Futuros posibles

La típica discusión de Twitter es a gritos entre extremos y la discusión forestal tiene harto de eso. Me llamó la atención eso sí que hubiera científicos—particularmente que jamás en su vida han trabajado en estos ecosistemas—contribuyendo al griterío.

Hay un libro que no he leído, pero que suena terriblemente interesante: Chile necesita un nuevo modelo forestal: propuestas ante desafíos climáticos, sociales y ambientales, publicado por la Agrupación de Ingenieros Forestales por el Bosque Nativo. Primer pelambre: este libro deberían hacerlo gratis en PDF o, por último, venderlo como ebook, porque hay que comunicar visiones alternativas del futuro (y algunos de nosotros ya dejamos de comprar libros en papel). El link es a un resumen de 15 páginas. ¿Qué tal si hacemos una “vaca” para hacer gratis este libro? Yo contribuyo feliz.

Una de las cosas que me desespera es que el conflicto es normalmente presentado como una dicotomía feroz: o manejamos bosque nativo o no es posible tener sector forestal productivo. El colmo de la falta de imaginación.

Justo esta semana apareció publicado un nuevo artículo Transitional forestry in New Zealand: re-evaluating the design and management of forest systems through the lens of forest purpose de Jones y colaboradores. Habla de sistemas forestales, para incluir todos los tipos de vegetación que queremos manejar en un mosaico de usos. Más aún, habla de gradientes de estos sistemas forestales de una manera que puede ser aplicado a muchos países, incluyendo Chile (lamentablemente todavía no está sci-hub).

Gradientes de sistemas forestales para enfrentar desafíos sociales, económicos y ecológicos inciertos.

Un elemento de inspiración: en Nueva Zelanda las tribus Maoríes están entre los mayores propietarios de bosques (tanto nativos como plantaciones). Varias tribus tienen joint-ventures con empresas forestales trabajando con plantaciones de exóticas. Las realidades son diferentes, pero una provocación es que IMHO Chile va 30 a 40 años detrás de NZ en cambios sociales. Por ejemplo, el Lake Taupō Forest Trust maneja 32 mil ha de tierras Maorí, con 23 mil ha de plantaciones, mayoritariamente de pino. Parte de los ingresos se dedica a expandir la restauración de bosque nativo.

Puedo pensar en un futuro en que hay una mayor diversidad de empresas forestales y en que las empresas grandes tienen una mejor relación con sus vecinos. Quizás hay gestos importantes que todavía tienen que suceder; imagino empresas donando terrenos circundantes a lugares poblados, reduciendo el riesgo de incendios. Imagino joint ventures entre comunidades Mapuche y empresas, con ingresos usados para hacer mejoras en la comunidad. Suena ingenuo en Twitter, pero son futuros posibles.

Música

No sé que música pusieron en la entrevista durante producción; me dijeron que sería Rock en inglés y yo podría haber sobrevivido con Rush. Sin embargo, ahora estoy en una onda más Jazz, así que hubiera escogido algo como “Running down the park” del grupo danés Little North. De pasada, dejemos claro que Neil Peart era esencialmente un baterista de Jazz 😉

Posibles conflictos de interés

Trabajo para la University of Canterbury, de donde provienen la mayoría de mis ingresos. A veces hago consultorías, aunque en los últimos años ha sido solo a empresas forestales de Nueva Zelanda. No he trabajado en Chile desde 1995.

Conozco personalmente a algunos de los autores de los artículos e informes que cito, de cuando trabajaba en la Universidad Austral (1993-1995) o de cuando era estudiante en la Universidad de Chile (1987-1992) o de mi trabajo en Australia y Nueva Zelanda (1996 -). Cito informes estadísticos producidos por organismos del Estado chileno (CONAF e INFOR); es probable que conozca a alguno de los autores, pero no tengo certeza.

Hay quienes puedan cuestionar, con razón, que no vivo en Chile. Por lo tanto ¿cómo puedo tener una opinión? Bueno, colaboro con colegas de universidades en Chile (ad-honorem, o sea por amor al arte) y conversamos todos los meses. La última vez que estuve conversando en persona con investigadores forestales en Chile fue en noviembre de 2022, para el Congreso Chileno de Ciencias Forestales, en que presenté un artículo.

« Older posts Newer posts »

© 2024 Palimpsest

Theme by Anders NorenUp ↑