# Instalar y cargar paquetes si es necesario
# install.packages("tidyverse")
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.3 ✔ tibble 3.3.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
set.seed(42)
df_lotes_r <- tibble( ID_Parcela = 1:200, Zona = sample(c(‘Norte’, ‘Sur’, ‘Este’, ‘Oeste’), 200, replace = TRUE), Textura_Suelo = sample(c(‘Arcilloso’, ‘Franco’, ‘Arenoso’), 200, replace = TRUE, prob = c(0.3, 0.5, 0.2)) ) %>% mutate( Humedad_base = case_when( Textura_Suelo == ‘Arcilloso’ ~ 30, Textura_Suelo == ‘Franco’ ~ 22, TRUE ~ 12 ), Humedad_ = Humedad_base + rnorm(200, mean = 0, sd = 3), Rendimiento_ton_ha = 3 + (Humedad_ * 0.15) + if_else(Textura_Suelo == ‘Franco’, 2.5, 0) + rnorm(200, mean = 0, sd = 1.5) ) %>% select(-Humedad_base)
print(head(df_lotes_r))
library(tidyverse)
set.seed(42)
df_lotes_r <- tibble( ID_Parcela = 1:200, Zona = sample(c(‘Norte’, ‘Sur’, ‘Este’, ‘Oeste’), 200, replace = TRUE), Textura_Suelo = sample(c(‘Arcilloso’, ‘Franco’, ‘Arenoso’), 200, replace = TRUE, prob = c(0.3, 0.5, 0.2)) ) %>% mutate( Humedad_base = case_when( Textura_Suelo == ‘Arcilloso’ ~ 30, Textura_Suelo == ‘Franco’ ~ 22, TRUE ~ 12 ), Humedad_ = Humedad_base + rnorm(200, mean = 0, sd = 3), Rendimiento_ton_ha = 3 + (Humedad_ * 0.15) + if_else(Textura_Suelo == ‘Franco’, 2.5, 0) + rnorm(200, mean = 0, sd = 1.5) ) %>% select(-Humedad_base)
print(head(df_lotes_r)) # 1. Resúmenes Estadísticos Agrupados con dplyr resumen_suelos_r <- df_lotes_r %>% group_by(Textura_Suelo) %>% summarise( Humedad_media = mean(Humedad_, na.rm = TRUE), Rendimiento_medio = mean(Rendimiento_ton_ha, na.rm = TRUE) )
print(resumen_suelos_r)
df_lotes_r %>% ggplot(aes(x = Textura_Suelo, y = Rendimiento_ton_ha, fill = Textura_Suelo)) + geom_boxplot() + labs(title = ‘Variabilidad del Rendimiento según el Tipo de Suelo’, x = ‘Textura del Suelo’, y = ‘Rendimiento (ton/ha)’) + theme_minimal() + scale_fill_viridis_d(option = “A”, begin = 0.5)
df_lotes_r %>% ggplot(aes(x = Humedad_, y = Rendimiento_ton_ha, color = Textura_Suelo)) + geom_point(alpha = 0.7) + geom_smooth(method = “lm”, se = FALSE) + facet_wrap(~ Zona, ncol = 2) + # Facetas por Zona, 2 columnas labs(title = ‘Relación Humedad-Rendimiento por Zona y Tipo de Suelo’, x = ‘Humedad (%)’, y = ‘Rendimiento (ton/ha)’, color = ‘Textura del Suelo’) + theme_minimal() + scale_color_viridis_d(option = “D”)
A continuación se explica el código línea por línea, tanto desde el punto de vista de **R** como de su interpretación en **estadística aplicada a la ingeniería agrícola**.
## 1. Instalación y carga de paquetes
```r
# Instalar y cargar paquetes si es necesario
# install.packages("tidyverse")
library(tidyverse)
#: inicia un comentario. R no ejecuta el texto que
sigue.install.packages("tidyverse"): instala el paquete
tidyverse. Esta línea solo debe ejecutarse si el paquete no
está instalado.library(tidyverse): carga el paquete en la sesión
actual.tidyverse incluye herramientas importantes como:
dplyr: manipulación y resumen de datos.tibble: creación de tablas modernas.ggplot2: elaboración de gráficos.tidyr: organización de datos.purrr, readr y otras herramientas.En estadística agrícola, estas herramientas permiten organizar datos de parcelas, resumir variables de suelo y analizar visualmente el rendimiento.
# Establecer semilla para reproducibilidad
set.seed(42)
set.seed(42): fija la semilla del generador de números
aleatorios.El código utiliza posteriormente:
sample(), para seleccionar categorías
aleatoriamente.rnorm(), para generar errores aleatorios con
distribución normal.La semilla garantiza que, al ejecutar nuevamente el código, se obtengan los mismos datos simulados.
Esto es importante para que un análisis sea:
La semilla 42 es arbitraria. El valor no tiene un
significado estadístico especial.
df_lotes_r <- tibble(
df_lotes_r <-: crea un objeto llamado
df_lotes_r.<- es el operador de asignación en R.tibble() crea una tabla de datos.El nombre puede interpretarse como:
df: data frame o tabla de datos;lotes: parcelas o lotes agrícolas;_r: versión elaborada en R. ID_Parcela = 1:200,
1:200 genera la secuencia de números enteros del 1 al
200.Se simulan 200 lotes o parcelas experimentales. El identificador no es una variable productiva; solo sirve para distinguir cada observación.
Zona = sample(c('Norte', 'Sur', 'Este', 'Oeste'), 200, replace = TRUE),
c(...) combina las cuatro categorías posibles.sample(...) selecciona aleatoriamente una
categoría.200 indica que se generan 200 valores.replace = TRUE permite que una misma zona sea
seleccionada varias veces.Cada parcela se asigna aleatoriamente a una de las cuatro zonas:
Zona es una variable cualitativa nominal. No existe un
orden natural entre Norte, Sur, Este y Oeste.
La zona puede representar diferentes sectores del campo, condiciones topográficas, regiones climáticas o unidades de manejo.
Textura_Suelo = sample(
c('Arcilloso', 'Franco', 'Arenoso'),
200,
replace = TRUE,
prob = c(0.3, 0.5, 0.2)
)
Arcilloso;Franco;Arenoso.prob = c(0.3, 0.5, 0.2) establece las probabilidades de
selección:| Textura | Probabilidad esperada |
|---|---|
| Arcilloso | 30 % |
| Franco | 50 % |
| Arenoso | 20 % |
Estas son probabilidades teóricas. En una muestra concreta, los porcentajes observados pueden ser ligeramente diferentes.
La textura del suelo afecta propiedades como:
Es una variable categórica nominal.
mutate()) %>%
mutate(
) cierra la creación inicial del
tibble.%>% es el operador pipe. Pasa el resultado de una
operación a la siguiente.mutate() crea nuevas columnas o modifica columnas
existentes.En este caso, se calculan:
Humedad_base = case_when(
Textura_Suelo == 'Arcilloso' ~ 30,
Textura_Suelo == 'Franco' ~ 22,
TRUE ~ 12
),
case_when() permite establecer condiciones
múltiples.
La lógica es:
TRUE ~ 12 funciona como condición final. En este caso,
corresponde al suelo arenoso.
Se está definiendo una relación determinista entre la textura y el nivel medio de humedad:
| Textura | Humedad base |
|---|---|
| Arcilloso | 30 |
| Franco | 22 |
| Arenoso | 12 |
La lógica representa que:
Los valores pueden interpretarse como porcentajes de humedad, aunque en datos reales habría que especificar si se trata de humedad gravimétrica, volumétrica u otra unidad.
Humedad_ = Humedad_base + rnorm(200, mean = 0, sd = 3),
rnorm(200, mean = 0, sd = 3) genera 200 valores
aleatorios de una distribución normal.mean = 0: el error promedio es cero.sd = 3: la desviación estándar del error es 3.Humedad_base.Matemáticamente, la variable simulada sigue aproximadamente:
Humedad observada = Humedad base + error aleatorio
La humedad no es exactamente igual para todas las parcelas con la misma textura. Existe variabilidad natural alrededor de la media.
Por ejemplo, para un suelo franco:
Humedad_ ≈ 22 ± variación aleatoria
La desviación estándar de 3 representa heterogeneidad entre parcelas, error de medición o factores no incluidos en el modelo.
Aunque dos parcelas tengan la misma textura, pueden diferir en humedad debido a:
El nombre Humedad_ termina en guion bajo, pero es válido
en R. Un nombre más descriptivo podría ser:
Humedad_porcentaje
Rendimiento_ton_ha = 3 + (Humedad_ * 0.15) +
if_else(Textura_Suelo == 'Franco', 2.5, 0) +
rnorm(200, mean = 0, sd = 1.5)
Esta expresión construye el rendimiento mediante varios componentes:
Rendimiento =
3
+ efecto de la humedad
+ efecto adicional del suelo franco
+ error aleatorio
3
Es el nivel inicial o intercepto del modelo.
Representa un rendimiento base de 3 toneladas por hectárea antes de considerar la humedad, el tipo de suelo y el error aleatorio.
(Humedad_ * 0.15)
Por cada unidad adicional de humedad, el rendimiento aumenta, en promedio, en:
0.15 ton/ha
Por ejemplo, una diferencia de 10 unidades de humedad se asociaría con:
10 × 0.15 = 1.5 ton/ha
El modelo supone una relación lineal positiva entre humedad y rendimiento. En términos prácticos, una mayor disponibilidad de agua favorece el crecimiento del cultivo, dentro del rango considerado.
Sin embargo, en la realidad esta relación podría no ser indefinidamente creciente. Un exceso de humedad puede provocar:
Por eso, para datos reales, puede ser necesario utilizar modelos no lineales.
if_else(Textura_Suelo == 'Franco', 2.5, 0)
if_else() asigna:
2.5 si el suelo es franco;0 para las demás texturas.Por tanto, el suelo franco recibe un incremento adicional de 2.5 ton/ha.
Esta variable representa un efecto categórico codificado manualmente. El modelo está suponiendo que, manteniendo constante la humedad, el suelo franco tiene una ventaja adicional de 2.5 ton/ha.
El suelo franco suele tener un equilibrio favorable entre:
No obstante, el valor de 2.5 es supuesto para la simulación, no una estimación proveniente de datos reales.
rnorm(200, mean = 0, sd = 1.5)
Se agrega variabilidad aleatoria con:
El error puede representar factores no incluidos, como:
) %>%
select(-Humedad_base)
select() selecciona columnas.-Humedad_base indica que esa columna debe
eliminarse.La columna se utilizó como variable intermedia, pero se elimina de la tabla final porque ya no es necesaria.
La tabla conserva:
ID_Parcela;Zona;Textura_Suelo;Humedad_;Rendimiento_ton_ha.Eliminar variables auxiliares ayuda a mantener una base limpia y evita confundir:
# Mostrar las primeras filas
print(head(df_lotes_r))
head(df_lotes_r) muestra normalmente las primeras seis
filas.print() imprime el resultado en la consola.Esto permite comprobar:
resumen_suelos_r <- df_lotes_r %>%
group_by(Textura_Suelo) %>%
summarise(
Humedad_media = mean(Humedad_, na.rm = TRUE),
Rendimiento_medio = mean(Rendimiento_ton_ha, na.rm = TRUE)
)
group_by(Textura_Suelo)
Divide las observaciones en grupos según:
Permite comparar el comportamiento de las parcelas según el tipo de suelo.
Humedad_media = mean(Humedad_, na.rm = TRUE)
mean() calcula la media aritmética.na.rm = TRUE indica que se ignoren los valores
ausentes, si existen.La media de humedad para cada textura se calcula como:
Suma de humedades del grupo / número de parcelas del grupo
Permite estimar la humedad promedio asociada a cada textura.
Se espera aproximadamente que:
Rendimiento_medio = mean(Rendimiento_ton_ha, na.rm = TRUE)
Calcula el rendimiento promedio de cada tipo de suelo.
Permite responder preguntas como:
Es importante distinguir entre:
Este código solo realiza estadística descriptiva. No prueba significancia estadística.
print(resumen_suelos_r)
Imprime la tabla de medias agrupadas.
Un resumen más completo podría incluir también:
n = n(),
desviacion = sd(Rendimiento_ton_ha, na.rm = TRUE)
La desviación estándar permitiría conocer la variabilidad dentro de cada textura.
df_lotes_r %>%
ggplot(aes(
x = Textura_Suelo,
y = Rendimiento_ton_ha,
fill = Textura_Suelo
)) +
ggplot() inicia un gráfico.aes() define las asociaciones entre variables y
elementos gráficos.En este caso:
x = Textura_Suelo: la textura aparece en el eje
horizontal.y = Rendimiento_ton_ha: el rendimiento aparece en el
eje vertical.fill = Textura_Suelo: cada textura tendrá un color
diferente. geom_boxplot() +
geom_boxplot() crea un diagrama de caja para cada
categoría.
Un boxplot muestra:
La caja contiene aproximadamente el 50 % central de los datos.
El gráfico permite comparar no solo el rendimiento promedio, sino también su estabilidad.
Por ejemplo, un tipo de suelo puede tener:
labs(
title = 'Variabilidad del Rendimiento según el Tipo de Suelo',
x = 'Textura del Suelo',
y = 'Rendimiento (ton/ha)'
) +
labs() modifica:
Las unidades ton/ha indican toneladas por hectárea.
theme_minimal() +
Aplica un diseño visual sencillo con pocos elementos decorativos.
Esto facilita la lectura de las diferencias entre grupos.
scale_fill_viridis_d(option = "A", begin = 0.5)
scale_fill_viridis_d() utiliza una paleta de colores
adecuada para variables discretas.option = "A" selecciona una variante de la paleta.begin = 0.5 comienza la paleta desde una parte
intermedia.Estas paletas suelen ser útiles porque presentan buen contraste y son relativamente accesibles para personas con dificultades para distinguir ciertos colores.
df_lotes_r %>%
ggplot(aes(
x = Humedad_,
y = Rendimiento_ton_ha,
color = Textura_Suelo
)) +
Se crea un gráfico de dispersión donde:
Cada punto representa una parcela.
Este gráfico permite estudiar simultáneamente:
geom_point(alpha = 0.7) +
geom_point() dibuja los puntos.alpha = 0.7 establece una transparencia del 70 %
aproximadamente.La transparencia ayuda a observar zonas donde varios puntos están superpuestos.
La nube de puntos permite evaluar visualmente:
geom_smooth(method = "lm", se = FALSE) +
geom_smooth() añade una línea suavizada o de
tendencia.method = "lm" utiliza un modelo lineal.se = FALSE oculta la banda de confianza.Como el color está asociado a Textura_Suelo, se ajusta
una línea separada para cada textura, dentro de cada zona.
En términos generales, para cada grupo se ajusta:
Rendimiento = intercepto + pendiente × Humedad + error
La pendiente indica cuánto cambia el rendimiento esperado cuando aumenta una unidad la humedad.
La línea no demuestra causalidad por sí sola. Solo muestra una asociación lineal en estos datos simulados.
Al ocultar la banda de confianza con se = FALSE, el
gráfico no muestra la incertidumbre de la estimación. Para visualizarla
se puede utilizar:
geom_smooth(method = "lm", se = TRUE)
facet_wrap(~ Zona, ncol = 2) +
facet_wrap(~ Zona) crea un panel separado para cada
zona.ncol = 2 organiza los paneles en dos columnas.~ Zona indica que las facetas se construyen usando la
variable Zona.Se obtienen cuatro paneles:
Permite verificar si la relación entre humedad y rendimiento cambia según la zona.
Por ejemplo, una zona podría mostrar menor rendimiento debido a:
En la simulación, sin embargo, la zona no se utiliza directamente para calcular el rendimiento. Por ello, cualquier diferencia entre zonas se debe principalmente al azar y a la composición de texturas de cada zona.
labs(
title = 'Relación Humedad-Rendimiento por Zona y Tipo de Suelo',
x = 'Humedad (%)',
y = 'Rendimiento (ton/ha)',
color = 'Textura del Suelo'
) +
Se asignan:
El título indica que se estudian simultáneamente:
theme_minimal() +
scale_color_viridis_d(option = "D")
theme_minimal() aplica un estilo limpio.scale_color_viridis_d() asigna colores a las categorías
de textura.option = "D" utiliza otra variante de la paleta
Viridis.Aquí se utiliza color, porque se colorean los puntos y
las líneas, mientras que en el boxplot se usó fill, porque
se rellenaban las cajas.
El código simula una situación agrícola en la que:
El modelo generador de los datos puede expresarse conceptualmente como:
Rendimiento =
3
+ 0.15 × Humedad
+ 2.5 si el suelo es franco
+ error
Por tanto, el análisis busca estudiar:
set.seed(42) garantiza reproducibilidad en R, pero no
necesariamente genera exactamente los mismos números que Python, aunque
se utilice la misma semilla.Para un análisis agrícola más completo, podría ajustarse un modelo como:
modelo <- lm(
Rendimiento_ton_ha ~ Humedad_ * Textura_Suelo + Zona,
data = df_lotes_r
)
summary(modelo)
Este modelo permitiría evaluar formalmente: