Gráficos sobre textura de suelos

Author

Carlos Carbajal Llosa

Published

May 19, 2022

Textura de los suelos

Como sabemos la textura representa una de las propiedades físicas más importantes de los suelos, en esta oportunidad vamos a emplear los paquetes de plotrix (J 2006) y soiltexture (Moeys 2018) para graficar valores en porcentajes de arena, limo y arcilla sobre un triangulo textural.

library(plotrix)
library(soiltexture)

Generación de datos de textura

Para nuestro ejemplo vamos a generar valores aleatorios para los porcetajes de arena (sand), limo (silt) y arcilla (clay), empleando para números enteros la función sample() y para números decimales la función runif().

Note

En caso disponga de datos en una tabla en formarto *.csv, se puede trabajar generando un dataframe con: df_textura <- read.csv("file.csv").

# Generación de valores aleatorios sobre textura
sand <- c(sample(0:60, 50, replace = T))
silt <- c(sample(0:40, 50, replace = T))
clay <- c(100-(sand+silt))
# Generación de números aleatorios referentes a valores de pH
ph <-  c(runif(50, min=4,max=8)) 


# Generación de nuestra tabla de datos en formato dataframe.
texture <- data.frame( "SAND" = sand, "SILT" = silt, "CLAY" = clay, "PH" = ph)

Generando gráficos empleando Plotrix

El paquete plotrix está destinado a proporcionar un método para obtener muchos tipos de gráficos especializados rápidamente, además tiene una fácil personalización de esos gráficos sin aprender una gran cantidad de sintaxis especializada. Para nuestros propósitos, dispone de la función soil.texture() que logra mostrar un triángulo de textura del suelo USDA con opciones sobre cuadrícula, etiquetas y puntos de textura del suelo.

Note

El paquete dispone también de la función get.soil.texture para generar de manera interactiva una matriz con los valores de arena, limo y arcilla.

text_data <-get.soil.texture(use.percentages=TRUE,cnames=c("arena","limo","arcilla"))

Para generar nuestro gráfico tener en cuenta solo las columnas con los valores porcentuales de arena limo y arcilla.

soil.texture(texture[, 1:3], main="Triangulo Textural de Suelos", 
             axis.labels = c("% Arena", "% Limo", "% Arcilla"),
             show.lines=TRUE,show.names=TRUE, col.names= "black",
             show.legend= FALSE, col.symbols="red", pch=16)

head(texture, n=20)
   SAND SILT CLAY       PH
1    35    9   56 4.031871
2    49    8   43 4.544261
3    43   16   41 6.831701
4    32   14   54 4.190381
5    32   22   46 4.270105
6     1   21   78 5.602790
7    11   21   68 4.403020
8    58   12   30 7.578773
9     6   13   81 5.264490
10   35   26   39 4.042491
11   38   25   37 4.271895
12   32   34   34 7.037972
13   58   11   31 4.531457
14   48   15   37 6.966209
15   16   37   47 7.182924
16   36   27   37 7.212386
17   10   18   72 7.079935
18   38   18   44 5.295287
19   28   15   57 4.992013
20    3    0   97 6.019785
Tip

Para cambiar la simbología de los puntos generados, podemos variar el argumento pch tomando como referencia la siguiente figura:

Generando gráficos empleando soiltexture

Con el paquete soiltexture disponemos de una caja de herramientas genérica para los datos de textura del suelo en R. Estas funciones pueden (1) trazar datos de textura del suelo (2) clasificar datos de textura del suelo, (3) transformar datos de textura del suelo desde y hacia diferentes sistemas de clases de tamaño de partículas, y (4) proporcionar algunas herramientas para ‘explorar’ los datos de textura del suelo (en el sentido de un análisis visual estadístico). Todas las herramientas están diseñadas para ser inherentemente clasificaciones de múltiples triángulos, múltiples geometrías y tamaños de partículas. También se proporciona una interfaz gráfica de usuario simple basada en texto: soiltexture_gui().

Entre los sistemas de clasificación de textura suelo existentes usaremos principalmente el USDA, pero podemos generar otros incluso superponer dos sistemas en un mismo gráfico.

TT.plot(
  class.sys = "USDA.TT",  # Seleccionando el sistema de clasificación del USDA
  lang = "es", # Personalizado al idioma español
  css.lab = c("Arcilla [%]", "Limo [%]", "Arena [%]"),
  class.p.bg.col = c("red", "purple", "brown", "wheat", "yellow", "pink", "beige", "orange", "green", "gray"),
  tri.data = texture,
  z.name = "PH",
  main = "Triángulo Textural de Suelo - USDA"
)

TT.plot(
  class.sys = "ISSS.TT",  
  css.lab = c("Arcilla [%]", "Limo [%]", "Arena [%]"),
  tri.data = texture,
  class.p.bg.col = TRUE,
  z.name = "PH",
  main = "Triángulo Textural de Suelo - ISSS"
)

TT.plot(
  class.sys = "HYPRES.TT",  
  css.lab = c("Arcilla [%]", "Limo [%]", "Arena [%]"),
  tri.data = texture,
  class.p.bg.col = TRUE,
  z.name = "PH",
  main = "Triángulo Textural de Suelo - HYPRES"
)

geom <- TT.plot(
  class.sys = "USDA.TT",
  main  = "Triángulos USDA y HYPRES superpuestos",
  css.lab = c("Arcilla [%]", "Limo [%]", "Arena [%]"),
  tri.data = texture
)
TT.classes(
  geo = geom,
  class.sys = "HYPRES.TT",
  class.line.col = "red",
  class.lab.col = "blue",
  lwd.axis = 3
)

Como apreciamos en el gráfico generado, se ha insertado los puntos ubicados en su respectiva clase textual que pertence (según el sistema elegido), además se incluye los valores de pH están representados en función al tamaño del diámetro del punto (valores bajos de pH presentan diámetros pequeños) y también se aprecia un gradiente de color para reforzar el efecto visual.

Generación de un mapa de calor con valores de pH

Siempre es importante evaluar un cuarto parámetro, pero si a eso le agregamos un mapa de calor generado a través de la interpolación de nuestro datos, en esta oportunidad emplea el método IDW (Inverse Distance Weighting). Para lograr ello, lo primero que hacemos es definir nuestros parámetros geométricos con TT.geo.get(), que nos permite determinar nuestra malla x-y en la que se calcula la distancia inversa.

# Definimos los parámetros geométricos de nuesto futuro gráfico
geo <- TT.geo.get()

# Calcular las distancias ponderadas inversas
iwd.res <- TT.iwd(
  geo = geo,
  tri.data = texture,
  z.name = "PH",
)
# Generar la vista del mapa de calor usando el IWD
TT.image(
  x = iwd.res,
  geo = geo,
  main = "Mapa de calor sobre pH en relación a la textura"
)

# Incorporar líneas en contorno
TT.contour(
  x = iwd.res,
  geo = geo, 
  add = TRUE, # Nos permite superponer las líneas sobre el mapa de calor
  lwd = 2,
  col = "#db139f93"
)
# Incorporar nuestro triangulo textural USDA
TT.plot(
  geo = geo,
  class.sys = "USDA.TT",
  lang = "es",
  css.lab = c("Arcilla [%]", "Limo [%]", "Arena [%]"),
  grid.show = FALSE,
  add = TRUE
)

Estimación de la densidad de probabilidad del Kernel 2D

La estimación de la densidad de probabilidad del kernel en dos dimensiones (x-y), se “envuelve” en la función TT.kde2d() para que lo podamos emplear siguiendo la misma estructura anterior con nuestros datos de textura. La gráfica es representada a modo de líneas de contorno usando TT.contour().

geo <- TT.geo.get()

# Calcular las distancias ponderadas inversas
kde.res <- TT.kde2d(
  geo = geo,
  tri.data = texture,
)

# Incorporar líneas en contorno
TT.contour(
  x = kde.res,
  geo = geo,
  main = "Densidad de Probabilidad estimada sobre datos de textura",
  lwd = 2,
  col = "red"
)
# Incorporar nuestro triangulo textural USDA
TT.plot(
  geo = geo,
  tri.data = texture,
  class.sys = "USDA.TT",
  lang = "es",
  css.lab = c("Arcilla [%]", "Limo [%]", "Arena [%]"),
  grid.show = FALSE,
  add = TRUE,
  col = "blue"
)

Generación de datos de clasificación de textura

Si bien el objetivo era mostrar los gráficos que podemos generar en base a nuestros resultados de contenidos de arena, limo y arcilla, incluyendo también como vimos la posibilidad de integrar una cuarta variable. Ahora veremos como podemos visualizar una tabla con las clases texturales determinadas en función a un sistema de clasificación seleccionado. Para lograrlo usaremos la función TT.points.in.classes(). En resumen se muestra en cada fila nuestra muestra de suelo y las columnas representan las clases texturales, los valores 0 representa que esta fuera de esa clase y el valor de 1 que esta dentro, mientras que 2 cuando cae “en un lado del polígono” y 3 cuando cae en “las esquinas del polígono”.

TT.points.in.classes(
  tri.data = texture[1:10, ], # visualizar las 10 primeras filas
  class.sys = "USDA.TT"
)
      Cl SiCl SaCl ClLo SiClLo SaClLo Lo SiLo SaLo Si LoSa Sa
 [1,]  1    0    0    0      0      0  0    0    0  0    0  0
 [2,]  0    0    1    0      0      0  0    0    0  0    0  0
 [3,]  1    0    0    0      0      0  0    0    0  0    0  0
 [4,]  1    0    0    0      0      0  0    0    0  0    0  0
 [5,]  1    0    0    0      0      0  0    0    0  0    0  0
 [6,]  1    0    0    0      0      0  0    0    0  0    0  0
 [7,]  1    0    0    0      0      0  0    0    0  0    0  0
 [8,]  0    0    0    0      0      1  0    0    0  0    0  0
 [9,]  1    0    0    0      0      0  0    0    0  0    0  0
[10,]  0    0    0    1      0      0  0    0    0  0    0  0

References

J, Lemon. 2006. “Plotrix: A Package in the Red Light District of r” 6: 8–12.
Moeys, Julien. 2018. “Soiltexture: Functions for Soil Texture Plot, Classification and Transformation.” https://CRAN.R-project.org/package=soiltexture.