Taller práctico - Geoestadística

Maestría en Geomática
Alicia Arévalo Robinson
05.03.2026

Punto 1. ¿Cuáles de los datos obtenidos corresponden a variables cuantitativas (discretas, continuas) cuales son regionalizadas, ¿cuáles a variables cualitativas? Indique la escala de medición a la cual pertenece cada variable.

Punto 2. Construya una tabla y la respectiva gráfica para alguna de las variables cualitativas. Exprese la información en términos absolutos, porcentuales, de un ejemplo de razón.

Variable cualitativa: Uso del suelo (landuse)

library(readxl)
library(ggplot2)

# Cargar dataset
meuse <- read_excel("meuse.xlsx")

# Frecuencias
fa  <- table(meuse$landuse)                    # absolutas
fr  <- prop.table(fa)                          # relativas (proporción)
fap <- cumsum(fa)                              # absolutas acumuladas
frp <- cumsum(fr)                              # relativas acumuladas

# Tabla 
tabla <- data.frame(
  Uso_Suelo        = names(fa),
  Frec_Absoluta    = as.integer(fa),
  Frec_Relativa    = round(as.numeric(fr), 4),
  Frec_Rel_Pct     = paste0(round(as.numeric(fr) * 100, 2), "%"),
  FA_Acumulada     = as.integer(fap)
)

print(tabla, row.names = FALSE)
##  Uso_Suelo Frec_Absoluta Frec_Relativa Frec_Rel_Pct FA_Acumulada
##         Aa             2        0.0129        1.29%            2
##         Ab             8        0.0516        5.16%           10
##         Ag             5        0.0323        3.23%           15
##         Ah            39        0.2516       25.16%           54
##         Am            22        0.1419       14.19%           76
##          B             3        0.0194        1.94%           79
##         Bw             6        0.0387        3.87%           85
##        DEN             1        0.0065        0.65%           86
##         Fh             1        0.0065        0.65%           87
##         Fw            10        0.0645        6.45%           97
##         Ga             3        0.0194        1.94%          100
##         NA             1        0.0065        0.65%          101
##        SPO             1        0.0065        0.65%          102
##        STA             2        0.0129        1.29%          104
##         Tv             1        0.0065        0.65%          105
##          W            50        0.3226       32.26%          155
tabla$Razon <- round(tabla$Frec_Absoluta / tabla$Frec_Absoluta[tabla$Uso_Suelo == "Ah"], 2)
print(tabla[, c("Uso_Suelo", "Razon")], row.names = FALSE)
##  Uso_Suelo Razon
##         Aa  0.05
##         Ab  0.21
##         Ag  0.13
##         Ah  1.00
##         Am  0.56
##          B  0.08
##         Bw  0.15
##        DEN  0.03
##         Fh  0.03
##         Fw  0.26
##         Ga  0.08
##         NA  0.03
##        SPO  0.03
##        STA  0.05
##         Tv  0.03
##          W  1.28

La categoría ‘Am’ tiene 0.56 veces la frecuencia de ‘Ah’.

p2 <- ggplot(meuse, aes(x = reorder(landuse, landuse, function(x) -length(x)))) +
  geom_bar(fill = "#2E86AB", color = "white", width = 0.7) +
  geom_text(stat = "count", aes(label = after_stat(count)), vjust = -0.4, size = 3.5) +
  labs(title = "Frecuencia de Uso del Suelo – Río Mosa",
       x = "Uso del suelo", y = "Frecuencia absoluta") +
  theme_minimal(base_size = 13)
p2

Punto 3. Construya una tabla de doble entrada y la respectiva gráfica para analizar conjuntamente las variables uso del suelo y frecuencia. ¿Son independientes las variables?

tabla_doble <- table(meuse$landuse, meuse$ffreq)
tabla_doble
##      
##        1  2  3
##   Aa   0  1  1
##   Ab   8  0  0
##   Ag   5  0  0
##   Ah  19 14  6
##   Am   6 11  5
##   B    3  0  0
##   Bw   3  1  2
##   DEN  0  1  0
##   Fh   1  0  0
##   Fw   5  4  1
##   Ga   3  0  0
##   NA   1  0  0
##   SPO  0  1  0
##   STA  0  2  0
##   Tv   0  1  0
##   W   30 12  8
meuse$ffreq <- factor(meuse$ffreq, 
                      levels = 1:3,
                      labels = c("1", "2", "3"))
meuse$landuse <- factor(meuse$landuse)
tabla_doble <- table(meuse$landuse, meuse$ffreq)

df_doble <- as.data.frame.table(tabla_doble)
names(df_doble) <- c("Landuse", "Ffreq", "Frecuencia")

ggplot(df_doble, aes(x = Landuse, y = Frecuencia, fill = Ffreq)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Uso del suelo vs Frecuencia de inundación",
       x = "Uso del suelo", y = "Frecuencia", fill = "Inundación") +
  theme_minimal()

chi_test <- chisq.test(tabla_doble)
## Warning in chisq.test(tabla_doble): Chi-squared approximation may be incorrect
print(chi_test)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla_doble
## X-squared = 42.24, df = 30, p-value = 0.06825
if (chi_test$p.value < 0.05) {
  cat("Con p =", round(chi_test$p.value, 4),
      "< 0.05, se rechaza la hipótesis de independencia.\n")
  cat("  Las variables 'uso del suelo' y 'frecuencia de inundación' no son independientes:\n")
  cat("  existe asociación estadísticamente significativa entre ellas.\n\n")
} else {
  cat("Con p =", round(chi_test$p.value, 4),
      "> 0.05, no se rechaza la hipótesis de independencia.\n")
  cat("  Las variables parecen ser independientes.\n\n")
}
## Con p = 0.0682 > 0.05, no se rechaza la hipótesis de independencia.
##   Las variables parecen ser independientes.

Punto 4. Para la variable cadmiun o copper realice un análisis exploratorio de datos. El análisis exploratorio de datos debe incluir: tabla de distribución de frecuencia apropiada (límites de cada marca de clase, marca media, frecuencias absolutas, frecuencias relativas; frecuencias absolutas y relativas acumuladas), justifique el número de marcas de clase que selecciono. Interprete la marca de clase más representativa, construya el histograma, polígono de frecuencias, ojiva y grafico circular. Comente los resultados de los gráficos. Además, calcular e interpretar: media aritmética, mediana, moda, desviación típica o estándar, error de estimación para la media, coeficiente de variación; percentil 25, 50, 75 y 69. ¿Qué tipo de simetría tienen los datos? Que puede concluir con respecto a la curtosis. ¿Los datos están agrupados o dispersos?. Construya una caja de bigotes e interprétela. Considera que hay valores atípicos, anómalos. Demuestre o refute que la variable cadmiun o copper tiene distribución normal. Justifique su respuesta.

# Limpiar columnas numéricas (coma decimal a punto)
cols_num <- c("cadmium")
meuse[cols_num] <- lapply(meuse[cols_num], function(x) as.numeric(gsub(",", ".", x)))

Variable cadmium

x <- meuse$cadmium
n <- length(x)
breaks <- seq(min(x), max(x), length.out = k + 1)
breaks[1]       <- breaks[1] - 0.001
breaks[k + 1]   <- breaks[k + 1] + 0.001
amplitude       <- breaks[2] - breaks[1]
marca_clase     <- (breaks[-1] + breaks[-(k+1)]) / 2

fa <- hist(x, breaks = breaks, plot = FALSE)$counts
fr <- fa / n
Fa <- cumsum(fa)
Fr <- cumsum(fr)

tabla_freq <- data.frame(
  Clase      = 1:k,
  LI         = round(breaks[-(k+1)], 3),
  LS         = round(breaks[-1], 3),
  MarcaClase = round(marca_clase, 3),
  FA         = fa,
  FR_pct     = round(fr * 100, 2),
  FA_Acum    = Fa,
  FR_Acum    = round(Fr, 4)
)
names(tabla_freq) <- c("Clase", "L.Inferior", "L.Superior", "M.Clase",
                        "FA", "FR_pct", "FA_Acum", "FR_Acum")
print(tabla_freq, row.names = FALSE)
##  Clase L.Inferior L.Superior M.Clase FA FR_pct FA_Acum FR_Acum
##      1      0.199      2.189   1.194 82  52.90      82  0.5290
##      2      2.189      4.178   3.183 37  23.87     119  0.7677
##      3      4.178      6.167   5.172  6   3.87     125  0.8065
##      4      6.167      8.156   7.161 12   7.74     137  0.8839
##      5      8.156     10.144   9.150  9   5.81     146  0.9419
##      6     10.144     12.133  11.139  5   3.23     151  0.9742
##      7     12.133     14.122  13.128  2   1.29     153  0.9871
##      8     14.122     16.111  15.117  0   0.00     153  0.9871
##      9     16.111     18.101  17.106  2   1.29     155  1.0000

Marca de clase más representativa: 1.194 mg/kg (clase 1, FA=82).
El intervalo con mayor número de observaciones se centra en 1.194 mg/kg. `

df_hist <- data.frame(x = x)
p4a <- ggplot(df_hist, aes(x = x)) +
  geom_histogram(breaks = breaks, fill = "#2E86AB", color = "white", alpha = 0.8) +
  geom_freqpoly(breaks = breaks, color = "#E84855", linewidth = 1) +
  labs(title = "Histograma y poligono de frecuencias",
       x = "Cadmium (mg/kg)", y = "Frecuencia absoluta") +
  theme_minimal(base_size = 13)
p4a

- Ojiva

df_ojiva <- data.frame(
  valor = breaks[-1],
  FA_Acum = c(Fa)
)
p4b <- ggplot(df_ojiva, aes(x = valor, y = FA_Acum)) +
  geom_line(color = "#E84855", linewidth = 1.2) +
  geom_point(color = "#E84855", size = 2.5) +
  labs(title = "Ojiva – Frecuencia Acumulada",
       x = "Cadmium (mg/kg)", y = "Frecuencia absoluta acumulada") +
  theme_minimal(base_size = 13)
p4b

- Gráfico circular (pie chart) – primeras 6 clases + resto

pie_data <- tabla_freq[, c("Clase", "FA")]
pie_data$label <- paste0("Clase ", pie_data$Clase,
                          "\n(", round(pie_data$FA / n * 100, 1), "%)")
p4c <- ggplot(pie_data, aes(x = "", y = FA, fill = factor(Clase))) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y") +
  scale_fill_brewer(palette = "Blues", name = "Clase") +
  #geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 3) +
  labs(title = "Grafico circular") +
  theme_void(base_size = 13)
p4c

- Estadísticos descriptivos

library(moments)

cat(sprintf("  n                     = %d\n", n))
##   n                     = 155
cat(sprintf("  Media aritmetica      = %.4f mg/kg\n", mean(x)))
##   Media aritmetica      = 3.2458 mg/kg
cat(sprintf("  Mediana               = %.4f mg/kg\n", median(x)))
##   Mediana               = 2.1000 mg/kg
cat(sprintf("  Moda                  = %.2f mg/kg\n", as.numeric(names(sort(table(x), decreasing = TRUE)[1]))))
##   Moda                  = 0.20 mg/kg
cat(sprintf("  Desviacion estandar   = %.4f mg/kg\n", sd(x)))
##   Desviacion estandar   = 3.5237 mg/kg
cat(sprintf("  Error estandar media  = %.4f mg/kg\n", sd(x) / sqrt(n)))
##   Error estandar media  = 0.2830 mg/kg
cat(sprintf("  Coeficiente variacion = %.2f %%\n", (sd(x) / mean(x)) * 100))
##   Coeficiente variacion = 108.56 %
cat(sprintf("  P25                   = %.2f mg/kg\n", quantile(x, 0.25)))
##   P25                   = 0.80 mg/kg
cat(sprintf("  P50                   = %.2f mg/kg\n", quantile(x, 0.50)))
##   P50                   = 2.10 mg/kg
cat(sprintf("  P69                   = %.2f mg/kg\n", quantile(x, 0.69)))
##   P69                   = 3.10 mg/kg
cat(sprintf("  P75                   = %.2f mg/kg\n", quantile(x, 0.75)))
##   P75                   = 3.85 mg/kg
cat(sprintf("  Asimetria (skewness)  = %.4f\n", skewness(x)))
##   Asimetria (skewness)  = 1.7788
cat(sprintf("  Curtosis (kurtosis)   = %.4f  (exceso: %.4f)\n", kurtosis(x), kurtosis(x)  - 3))
##   Curtosis (kurtosis)   = 6.1299  (exceso: 3.1299)
p4d <- ggplot(df_hist, aes(y = x, x = "")) +
  geom_boxplot(fill = "#AED6F1", color = "#1A5276",
               outlier.color = "red", outlier.shape = 16, outlier.size = 2) +
  stat_summary(fun = mean, geom = "point", shape = 18, size = 4, color = "#E84855") +
  labs(title = "Diagrama de caja y bigotes",
       subtitle = "Punto rojo = media; puntos rojos = valores atípicos",
       x = "", y = "Cadmium (mg/kg)") +
  theme_minimal(base_size = 13)
p4d

- Valores atípicos

lim_inf <- quantile(x, 0.25) - 1.5 * IQR(x)
lim_sup <- quantile(x, 0.75) + 1.5 * IQR(x)
atipicos <- x[x < lim_inf | x > lim_sup]

cat("\n── Valores atípicos ────────────────────────────────\n")
## 
## ── Valores atípicos ────────────────────────────────
cat(sprintf("  Límite inferior (Q1 - 1.5·RIC) = %.4f\n", lim_inf))
##   Límite inferior (Q1 - 1.5·RIC) = -3.7750
cat(sprintf("  Límite superior (Q3 + 1.5·RIC) = %.4f\n", lim_sup))
##   Límite superior (Q3 + 1.5·RIC) = 8.4250
cat(sprintf("  Valores atípicos detectados: %d\n", length(atipicos)))
##   Valores atípicos detectados: 15
if (length(atipicos) > 0) {
  cat("  Valores:", paste(round(sort(atipicos), 2), collapse = ", "), "\n")
  cat("  → Sí existen valores atípicos (anómalos), todos por encima del límite superior.\n")
  cat("    Posiblemente corresponden a sitios con contaminación localizada extrema.\n\n")
}
##   Valores: 8.6, 8.7, 9.4, 9.4, 9.4, 9.5, 10.8, 10.9, 11.2, 11.7, 12, 12.9, 14.1, 17, 18.1 
##   → Sí existen valores atípicos (anómalos), todos por encima del límite superior.
##     Posiblemente corresponden a sitios con contaminación localizada extrema.