CARGA DE DATOS

knitr::opts_chunk$set(
    echo = TRUE,                   # Muestra el código R en el reporte final.
    message = FALSE,
    warning = FALSE,               # Message y warning evitan que se impriman alertas o mensajes de carga estorbosos en el HTML.
    fig.align = "center"           # Centra automáticamente todas las gráficas generadas.
)

datos <- read.csv("C:/Users/USER/Documents/PROYECTO ESTADISTICA/CMDB_Data.csv", 
                  header = TRUE, # Indica que la primera fila contienen los nombres de las variables.
                  sep = ";",     # Define que los puntos y comas es el separador de las columnas del archivo.
                  dec = ".",     # Establece el punto como el operador decimal para los números.
                  fileEncoding = "latin1")

# Verificación inicial del set de datos
str(datos)
## 'data.frame':    1366 obs. of  103 variables:
##  $ ï..LAB_ID            : chr  "C355417" "C360759" "C360762" "C360763" ...
##  $ PREVIOUS_LAB_ID1     : chr  "" "" "" "" ...
##  $ PREVIOUS_LAB_ID2     : chr  "" "" "" "" ...
##  $ PREVIOUS_LAB_ID3     : chr  "" "" "" "" ...
##  $ FIELD_ID             : chr  "RM0001" "RM0027" "RM0030" "RM0031" ...
##  $ JOB_ID               : chr  "MRP11968" "MRP12307" "MRP12307" "MRP12307" ...
##  $ PREVIOUS_JOB_ID1     : chr  "" "" "" "" ...
##  $ PREVIOUS_JOB_ID2     : chr  "" "" "" "" ...
##  $ PREVIOUS_JOB_ID3     : chr  "" "" "" "" ...
##  $ SUBMITTER            : chr  "Rare Metals Task" "Rare Metals Task" "Rare Metals Task" "Rare Metals Task" ...
##  $ PROJECT_NAME         : chr  "Critical and Rare Metals" "Critical and Rare Metals" "Critical and Rare Metals" "Critical and Rare Metals" ...
##  $ DATE_SUBMITTED       : chr  "30/6/2011" "31/8/2011" "31/8/2011" "31/8/2011" ...
##  $ COLLECTION           : chr  "Mackay-Keck Ore Deposits Collection" "Mackay-Stanford Ore Deposits Collection" "Mackay-Stanford Ore Deposits Collection" "Mackay-Stanford Ore Deposits Collection" ...
##  $ COLLECTION_ID        : chr  "PHNC08_39_1183" "OD21441" "OD22811" "OD25716" ...
##  $ CONTINENT            : chr  "North America" "South America" "South America" "Africa" ...
##  $ COUNTRY              : chr  "United States" "Chile" "Chile" "South Africa" ...
##  $ STATE_PROVINCE       : chr  "Nevada" "Antofagasta" "Tarapacá" "Transvaal" ...
##  $ COUNTY               : chr  "Lyon" "El Loa" "El Tamarugal" "" ...
##  $ DISTRICT_NAME        : chr  "Yerington" "Chuquicamata" "Collahuasi/Quebrada Blanca" "" ...
##  $ DEPOSIT_NAME         : chr  "Pumpkin Hollow" "" "" "" ...
##  $ MINE_NAME            : chr  "Pumpkin Hollow" "Chuquicamata mine" "Collahuasi district" "" ...
##  $ DISTRICT_NAME_COLLECT: chr  "Yerington" "" "" "" ...
##  $ DEPOSIT_NAME_COLLECT : chr  "" "" "" "" ...
##  $ MINE_NAME_COLLECT    : chr  "Pumpkin Hollow" "Chuquicamata" "Poduosa mine" "Messina Mines Ltd." ...
##  $ LOCATE_DESC          : chr  "" "" "Level 25" "" ...
##  $ LATITUDE             : chr  "38,94021" "-22,2871" "-21,0309" "-24,7" ...
##  $ LONGITUDE            : chr  "-119,05178" "-68,8991" "-68,74951" "29,3" ...
##  $ DATUM                : chr  "WGS84" "WGS84" "WGS84" "" ...
##  $ LATITUDE_COLLECT     : chr  "38,92492" "22,28944" "" "" ...
##  $ LONGITUDE_COLLECT    : chr  "-119,1071" "-68,90111" "" "" ...
##  $ DATUM_COLLECT        : chr  "" "WGS84" "" "" ...
##  $ COORDINATES_QUAL     : chr  "100 m" "Exact" "" "" ...
##  $ COORDINATES_SOURCE   : chr  "1) iTouchMap.com, approx, A. Orkild-Norton; 2) Mineral Resource Deposit Database Deposit ID 10174173, ore body, M. Granitto" "1) Mindat.org, approx, A. Orkild-Norton; 2) Open-File Report 2017-1079 ID 549, mine, M. Granitto" "1) No coordinates; 2) Mineral Resource Deposit Database Deposit ID 10057511, district, M. Granitto" "1) No coordinates; 2) Google Earth Pro, approx ctr of former province of Transvaal, M. Granitto" ...
##  $ PRIMARY_CLASS        : chr  "rock" "rock" "rock" "rock" ...
##  $ SYSTEM_TYPE          : chr  "IOA-IOCG" "Porphyry Cu-Mo-Au" "Porphyry Cu-Mo-Au" "IOA-IOCG" ...
##  $ DEPOSIT_TYPE         : chr  "IOCG" "Supergene Cu" "Porphyry Cu" "IOCG" ...
##  $ SAMPLE_DESC          : chr  "Nearly solid chalcopyrite mixed with small light brown irregular inclusions of unknown mineralogy; clouds of ma"| __truncated__ "Chalcocite-bronchatite-antlerite(?); highly microfractured igneous rock with green copper sulfates coating microfractures" "Bornite-chalcopyrite; mostly massive chalcopyrite with numerous inclusions of micro-chalcopyrite and widely sca"| __truncated__ "Massive chalcopyrite, IOCG in shear zone; mostly massive fine grain cuprite with widely distributed malachite t"| __truncated__ ...
##  $ Al_pct_AES_ST        : chr  "0,33" "6,65" "0,46" "0,7" ...
##  $ Ca_pct_AES_ST        : chr  "1,1" "0,4" "-0,1" "0,3" ...
##  $ Fe_pct_AES_ST        : chr  "42,4" "0,25" "6,98" "27,8" ...
##  $ K_pct_AES_ST         : chr  "-0,1" "6,1" "0,2" "-0,1" ...
##  $ Mg_pct_AES_ST        : chr  "0,57" "0,1" "0,01" "0,33" ...
##  $ Mn_pct_AES_ST        : chr  "0,02" "-0,01" "-0,01" "-0,01" ...
##  $ P_pct_AES_ST         : chr  "-0,01" "0,01" "0,05" "0,01" ...
##  $ S_pct_AES_ST         : chr  "" "" "" "" ...
##  $ Si_pct_AES_ST        : chr  "" "" "" "" ...
##  $ Ti_pct_AES_ST        : chr  "0,01" "0,11" "-0,01" "-0,01" ...
##  $ F_pct_ISE_Fuse       : chr  "" "" "" "" ...
##  $ Ag_ppm_MS_ST         : chr  "58" "6" "468" "16" ...
##  $ As_ppm_MS_ST         : chr  "-30" "-30" "90" "-30" ...
##  $ Au_ppm               : chr  "" "" "" "" ...
##  $ Au_AM                : chr  "" "" "" "" ...
##  $ B_ppm_AES_ST         : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ Ba_ppm_AES_ST        : chr  "-0,5" "924" "121" "174" ...
##  $ Be_ppm_AES_ST        : int  -5 -5 -5 -5 -5 -5 -5 -5 -5 -5 ...
##  $ Bi_ppm_MS_ST         : chr  "1,5" "3,6" "190" "0,4" ...
##  $ Cd_ppm_MS_ST         : chr  "3,6" "-0,2" "0,9" "-0,2" ...
##  $ Ce_ppm_MS_ST         : chr  "0,4" "8,8" "16,3" "3,5" ...
##  $ Co_ppm_MS_ST         : chr  "209" "-0,5" "1,3" "44,8" ...
##  $ Cr_ppm_AES_ST        : int  -10 -10 -10 30 20 20 60 40 20 10 ...
##  $ Cs_ppm_MS_ST         : chr  "0,5" "1,4" "0,2" "-0,1" ...
##  $ Cu_ppm_AES_ST        : chr  "50000,11111" "23300" "50000,11111" "50000,11111" ...
##  $ Dy_ppm_MS_ST         : chr  "-0,05" "0,32" "1,38" "0,37" ...
##  $ Er_ppm_MS_ST         : chr  "-0,05" "0,22" "0,77" "0,23" ...
##  $ Eu_ppm_MS_ST         : chr  "-0,05" "0,14" "0,17" "0,1" ...
##  $ Ga_ppm_MS_ST         : chr  "5" "15" "6" "3" ...
##  $ Gd_ppm_MS_ST         : chr  "-0,05" "0,45" "1,5" "0,39" ...
##  $ Ge_ppm_MS_ST         : int  -1 5 -1 -1 3 8 8 1 2 2 ...
##  $ Hf_ppm_MS_ST         : int  -1 4 -1 -1 5 13 12 2 3 6 ...
##  $ Ho_ppm_MS_ST         : chr  "-0,05" "0,07" "0,25" "0,07" ...
##  $ In_ppm_MS_ST         : chr  "6,4" "-0,2" "3,7" "0,2" ...
##  $ La_ppm_MS_ST         : chr  "0,2" "4,6" "7,2" "1,7" ...
##  $ Li_ppm_AES_ST        : int  -10 -10 -10 -10 30 20 20 20 -10 20 ...
##  $ Lu_ppm_MS_ST         : chr  "-0,05" "-0,05" "0,08" "-0,05" ...
##  $ Mo_ppm_MS_ST         : chr  "-2" "60" "3" "2" ...
##  $ Nb_ppm_MS_ST         : chr  "-1" "4" "-1" "-1" ...
##  $ Nd_ppm_MS_ST         : chr  "0,2" "3,8" "9,1" "1,7" ...
##  $ Ni_ppm_AES_ST        : chr  "144" "6" "-5" "48" ...
##  $ Pb_ppm_MS_ST         : chr  "23" "16" "188" "39" ...
##  $ Pd_ppm_FA_MS         : chr  "" "" "" "" ...
##  $ Pr_ppm_MS_ST         : chr  "-0,05" "1,09" "2,21" "0,46" ...
##  $ Pt_ppm_FA_MS         : chr  "" "" "" "" ...
##  $ Rb_ppm_MS_ST         : chr  "1,2" "148" "7,1" "0,7" ...
##  $ Re_ppm_MS_HF         : chr  "" "" "" "" ...
##  $ Sb_ppm_MS_ST         : chr  "1,2" "2,4" "2,9" "0,3" ...
##  $ Sc_ppm_AES_ST        : int  -5 -5 -5 -5 11 6 15 10 5 6 ...
##  $ Se_ppm_MS_ST         : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ Sm_ppm_MS_ST         : chr  "-0,1" "0,6" "1,6" "0,4" ...
##  $ Sn_ppm_MS_ST         : chr  "2" "3" "106" "-1" ...
##  $ Sr_ppm_AES_ST        : chr  "26,6" "114" "22,5" "38,4" ...
##  $ Ta_ppm_MS_ST         : chr  "-0,5" "-0,5" "-0,5" "-0,5" ...
##  $ Tb_ppm_MS_ST         : chr  "-0,05" "0,07" "0,23" "-0,05" ...
##  $ Te_ppm_MS_ST         : chr  "" "" "" "" ...
##  $ Th_ppm_MS_ST         : chr  "0,2" "9,7" "2,6" "0,2" ...
##  $ Tl_ppm_MS_ST         : chr  "-0,5" "0,5" "-0,5" "-0,5" ...
##  $ Tm_ppm_MS_ST         : chr  "-0,05" "-0,05" "0,08" "-0,05" ...
##  $ U_ppm_MS_ST          : chr  "0,3" "1,75" "0,63" "34,8" ...
##  $ V_ppm_AES_ST         : int  51 24 -5 493 68 20 40 159 39 61 ...
##  $ W_ppm_MS_ST          : chr  "-1" "28" "22" "11" ...
##   [list output truncated]

ANÁLISIS DE FRECUENCIAS: CONCENTRACIÓN DEL FLÚOR (F)

# Cargar las librerías necesarias
library(dplyr)
library(gt)

#----------------------- PROCESAMIENTO F_pct_ISE_Fuse -----------------------

# 1. Limpieza y preparación de la variable (conversión de coma a punto)
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))

# Separar registros con concentraciones válidas (>= 0) de los nulos o negativos
f_numerico <- datos$F_pct_ISE_Fuse[datos$F_pct_ISE_Fuse >= 0 & !is.na(datos$F_pct_ISE_Fuse)]
n_sin_datos_f <- sum(is.na(datos$F_pct_ISE_Fuse) | datos$F_pct_ISE_Fuse < 0)

# 2. Tabla de Frecuencias de los valores geoquímicos reales
TDF_VALIDOS_F <- as.data.frame(table(f_numerico), stringsAsFactors = FALSE)
colnames(TDF_VALIDOS_F) <- c("CATEGORIA", "ni")

# Convertir categoría a numérico para ordenar de menor a mayor concentración (%)
TDF_VALIDOS_F$CATEGORIA <- as.numeric(TDF_VALIDOS_F$CATEGORIA)
TDF_VALIDOS_F <- TDF_VALIDOS_F[order(TDF_VALIDOS_F$CATEGORIA), ]

# Definición de horizontes cuantitativos
total_variable_f <- sum(TDF_VALIDOS_F$ni)        # Total con lecturas de Flúor
total_general_f  <- total_variable_f + n_sin_datos_f # Total absoluto de la matriz

# 3. Agrupación: Top 10 valores de concentración más bajos + Otros
if(nrow(TDF_VALIDOS_F) > 10) {
  tabla_top_f <- head(TDF_VALIDOS_F, 10)
  sum_otros_f <- sum(TDF_VALIDOS_F$ni[11:nrow(TDF_VALIDOS_F)])
  fila_otros_f <- data.frame(CATEGORIA = "Otras Concentraciones", ni = sum_otros_f)
  tabla_final_base_f <- rbind(tabla_top_f, fila_otros_f)
} else {
  tabla_final_base_f <- TDF_VALIDOS_F
}

# Convertir CATEGORIA a carácter para permitir el ensamblaje de totales
tabla_final_base_f$CATEGORIA <- as.character(tabla_final_base_f$CATEGORIA)

# 4. Calcular frecuencias relativas (hi) respecto al total general del proyecto
tabla_final_base_f$hi <- round((tabla_final_base_f$ni / total_general_f) * 100, 4)

# 5. FILA DEL TOTAL EXCLUSIVO DE LA VARIABLE (Muestras con datos de F)
fila_total_var_f <- data.frame(
  CATEGORIA = "TOTAL VARIABLE (F)", 
  ni = total_variable_f,
  hi = round((total_variable_f / total_general_f) * 100, 4)
)

# 6. FILA DE CONTRASTE: REGISTROS SIN INFORMACIÓN ANALÍTICA
fila_sin_datos_f <- data.frame(
  CATEGORIA = "Sin Datos", 
  ni = n_sin_datos_f,
  hi = round((n_sin_datos_f / total_general_f) * 100, 4)
)

# 7. FILA DEL TOTAL GENERAL DEL PROYECTO
fila_total_general_f <- data.frame(
  CATEGORIA = "TOTAL GENERAL", 
  ni = total_general_f,
  hi = 100 # Forzado para cierre perfecto de balance estadístico
)

# Consolidar toda la matriz de datos en orden lógico estructurado
tabla_final_f <- rbind(tabla_final_base_f, fila_total_var_f, fila_sin_datos_f, fila_total_general_f)
colnames(tabla_final_f) <- c("Valor F (%)", "ni", "hi")

#----------------------- GENERAR SALIDA ESTÉTICA CON 'gt' -----------------------
tabla_fluor_completa_gt <- tabla_final_f %>%
  gt() %>%
  tab_header(
    title = md("**Tabla N° 1**"),
    subtitle = md("Distribución de frecuencias para concentraciones de Flúor (F)")
  ) %>%
  tab_source_note(
    source_note = md("Autores: Grupo 1 <br> Semestre 2026 - 2026")
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black",
    row.striping.include_table_body = TRUE
  )

# Renderizar la tabla en el documento
tabla_fluor_completa_gt
Tabla N° 1
Distribución de frecuencias para concentraciones de Flúor (F)
Valor F (%) ni hi
0.016 1 0.0732
0.018 1 0.0732
0.02 1 0.0732
0.024 1 0.0732
0.044 1 0.0732
0.047 1 0.0732
0.067 1 0.0732
0.073 1 0.0732
0.075 1 0.0732
0.077 1 0.0732
Otras Concentraciones 11 0.8053
TOTAL VARIABLE (F) 21 1.5373
Sin Datos 1345 98.4627
TOTAL GENERAL 1366 100.0000
Autores: Grupo 1
Semestre 2026 - 2026

POLÍGONO DE FRECUENCIA

#----------------------- PROCESAMIENTO AUTOMÁTICO F_PCT_ISE_FUSE -----------------------

# 1. Conversión de la variable a numérico y limpieza de datos (Flúor)
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))
F_VAR <- datos$F_pct_ISE_Fuse[!is.na(datos$F_pct_ISE_Fuse) & datos$F_pct_ISE_Fuse >= 0]

#----------------------- EXTRACCIÓN METODOLÓGICA DE STURGES -----------------------

# 2. Calculamos los parámetros de Sturges para el Flúor automáticamente
n_total_f <- length(F_VAR)
k_sturges_f <- floor(1 + 3.322 * log10(n_total_f)) 

# 3. Definimos los cortes de intervalos (breaks) usando el rango real del Flúor
rango_f <- max(F_VAR) - min(F_VAR)
amplitud_f <- rango_f / k_sturges_f
breaks_sturges_f <- seq(from = min(F_VAR), by = amplitud_f, length.out = k_sturges_f + 1)

# 4. CAPTURA DE DATOS OCULTOS: Agrupación y conteo en memoria para Flúor
hist_objeto_f <- hist(F_VAR, breaks = breaks_sturges_f, plot = FALSE, right = FALSE)

#-----------------------  ANCLAJE A CERO -----------------------

# 5. Creamos las clases vacías a los extremos para que el polígono cierre en el eje X
mc_inicio_f <- hist_objeto_f$mids[1] - amplitud_f
mc_final_f  <- hist_objeto_f$mids[length(hist_objeto_f$mids)] + amplitud_f

# Unimos los vectores definitivos para el gráfico (Marcas de Clase y Frecuencias n)
marcas_clase_f <- c(mc_inicio_f, hist_objeto_f$mids, mc_final_f)
frecuencias_f  <- c(0, hist_objeto_f$counts, 0)

# Detectamos la frecuencia máxima real del flúor para el eje Y
max_y_f <- max(frecuencias_f)

#----------------------- GRAFICAR POLÍGONO DE FRECUENCIAS (Flúor) -----------------------
par(mar = c(5, 5, 4, 2))

# 6. Inicializar el lienzo con los límites calculados para el Flúor
plot(marcas_clase_f, frecuencias_f,
     type = "n",
     main = "Gráfica 1: Polígono de Frecuencias Absolutas de Flúor (F)",
     xlab = "Concentración de Flúor - F (%)",
     ylab = "Frecuencia Absoluta (n muestras)",
     xlim = c(min(breaks_sturges_f), max(breaks_sturges_f)), # Ajuste exacto a los límites de flúor
     ylim = c(0, max_y_f * 1.1),                         # Margen del 10% superior libre
     xaxt = "n", yaxt = "n",
     panel.first = grid(nx = NULL, ny = NULL, col = "gray90")) 

# 7. Dibujar el polígono
lines(marcas_clase_f, frecuencias_f, type = "b", pch = 19, col = "chocolate4", lwd = 3)

# 8. Relleno translúcido a juego debajo de la curva
polygon(marcas_clase_f, frecuencias_f, col = rgb(0.55, 0.27, 0.07, 0.12), border = NA)

#----------------------- PERSONALIZACIÓN DE EJES CONTINUOS -----------------------

# Eje X: Imprime los límites reales de Sturges para el flúor (3 decimales)
axis(1, at = breaks_sturges_f, labels = round(breaks_sturges_f, 3), cex.axis = 0.75, las = 1)

# Eje Y: Imprime marcas proporcionales y ancla el valor de n más alto detectado
marcas_eje_y_f <- pretty(c(0, max_y_f))
marcas_eje_y_f <- marcas_eje_y_f[marcas_eje_y_f < (max_y_f * 0.9)] 
axis(2, at = c(marcas_eje_y_f, max_y_f), labels = c(marcas_eje_y_f, max_y_f), las = 1, cex.axis = 0.8)

ANÁLISIS GRÁFICO: HISTOGRAMA DISTRIBUCIÓN DEL FLÚOR

#----------------------- PROCESAMIENTO F_pct_ISE_Fuse -----------------------

# 1. Conversión de F_pct_ISE_Fuse a numérico (blindado contra comas y textos)
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))

# Creamos variable de trabajo para las gráficas y FILTRAMOS los negativos
F_VAR <- datos$F_pct_ISE_Fuse
F_VAR <- F_VAR[F_VAR >= 0 & !is.na(F_VAR)] # Mantenemos solo valores >= 0

#----------------------- TABLA DE FRECUENCIAS SIMPLIFICADA -----------------------
# Al ser continua, agrupamos por rangos automáticos (bins) para que la tabla sea legible

k_simplificado <- 5
# Usamos pretty para obtener cortes redondeados y estéticos
breaks_s <- pretty(F_VAR, n = k_simplificado)
HistogramaF <- hist(F_VAR, breaks = breaks_s, plot = FALSE)

# 2. Generación del Histograma
# Mantenemos la lógica original aplicada ahora al Flúor filtrado
hist(F_VAR,
     breaks = breaks_s,
     main = "Gráfica 2: Distribución de F_pct_ISE_Fuse (Simplificada)",
     xlab = "Concentración de F (%)",
     ylab = "Cantidad de muestras",
     col = "thistle",  # Color ajustado para el Flúor
     right = FALSE)

ANÁLISIS DESCRIPTIVO Y AGRUPACIÓN EN CLASES (STRUGES) DEL FLÚOR

# Asegúrate de cargar las librerías al inicio del chunk
library(dplyr)
library(gt)

#------------------------- PREPARACIÓN DE DATOS -------------------------
# reemplazamos comas por puntos
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))

# Creamos la variable de trabajo FLUOR asegurando que los datos estén limpios y sin negativos
FLUOR <- datos$F_pct_ISE_Fuse[!is.na(datos$F_pct_ISE_Fuse) & datos$F_pct_ISE_Fuse >= 0]

#------------------------- ANÁLISIS DE CONCENTRACIÓN (ESTADÍSTICOS) -------------------------
cat("\n=======================================================\n")
## 
## =======================================================
cat("ANÁLISIS DE CONCENTRACIÓN (F_pct_ISE_Fuse):\n")
## ANÁLISIS DE CONCENTRACIÓN (F_pct_ISE_Fuse):
cat("La concentración promedio es: ", round(mean(FLUOR, na.rm = TRUE), 2), " % \n")
## La concentración promedio es:  0.6  %
cat("La concentración máxima detectada es: ", max(FLUOR, na.rm = TRUE), " % \n")
## La concentración máxima detectada es:  3.73  %
cat("Total de muestras analizadas: ", sum(!is.na(FLUOR)), " registros \n")
## Total de muestras analizadas:  21  registros
cat("=======================================================\n")
## =======================================================
#------------------------- TABLA DE FRECUENCIAS - STURGES -------------------------
# 1. Parámetros básicos: Rango, Número de clases (Sturges) y Amplitud
R <- max(FLUOR, na.rm = TRUE) - min(FLUOR, na.rm = TRUE)
k <- floor(1 + 3.322 * log10(length(FLUOR)))
A <- R / k

# 2. Definición de límites y Marcas de Clase (MC)
liminf <- seq(from = min(FLUOR, na.rm = TRUE), by = A, length.out = k)
limsup <- liminf + A
MC <- (liminf + limsup) / 2

# 3. Conteo de frecuencias absolutas por clase (n)
n <- numeric(k)
for (i in 1:k) {
  if (i == k) {
    n[i] <- sum(FLUOR >= liminf[i] & FLUOR <= limsup[i], na.rm = TRUE)
  } else {
    n[i] <- sum(FLUOR >= liminf[i] & FLUOR < limsup[i], na.rm = TRUE)
  }
}

# 4. Cálculos de frecuencias relativas y acumuladas
hi <- (n / sum(n)) * 100
Ni_asc <- cumsum(n)             # Frecuencia absoluta acumulada (ascendente)
Hi_asc <- cumsum(hi)            # Frecuencia relativa acumulada (ascendente)
Ni_desc <- rev(cumsum(rev(n)))  # Frecuencia absoluta acumulada (descendente)
Hi_desc <- rev(cumsum(rev(hi))) # Frecuencia relativa acumulada (descendente)

#------------------------- CONSTRUCCIÓN DE LA TABLA -------------------------
TablaF_Sturges <- data.frame(
  Clase = as.character(1:k), # Se convierte a carácter para poder añadir "TOTALES" luego
  liminf = round(liminf, 3),
  limsup = round(limsup, 3),
  MC = round(MC, 3),
  n = n,
  hi = round(hi, 2),
  Ni_asc = Ni_asc,
  Hi_asc = round(Hi_asc, 2),
  Ni_desc = Ni_desc,
  Hi_desc = round(Hi_desc, 2)
)

# Fila de TOTALES para el cierre de balance formal
fila_totales_F <- data.frame(
  Clase = "**TOTALES**",
  liminf = NA,
  limsup = NA,
  MC = NA,
  n = sum(n),
  hi = 100,
  Ni_asc = NA,
  Hi_asc = 100,
  Ni_desc = NA,
  Hi_desc = 100
)

# Unión de cuerpo y totales
TablaF_Final <- rbind(TablaF_Sturges, fila_totales_F)

#------------------------- MOSTRAR TABLA FINAL CON 'gt' -------------------------
tabla_sturges_f_gt <- TablaF_Final %>%
  gt() %>%
  tab_header(
    title = md("**Tabla N° 2**"),
    subtitle = md("Distribución de frecuencias para concentraciones de Flúor (F_pct_ISE_Fuse) <br> mediante Regla de Sturges")
  ) %>%
  tab_source_note(
    source_note = md("Autores: Grupo 1 <br> Semestre 2026 - 2026")
  ) %>%
  fmt_markdown(columns = Clase) %>% # Renderiza correctamente las negritas de "**TOTALES**"
  cols_label(
    Clase = "Clase",
    liminf = "Linf (%)",
    limsup = "Lsup (%)",
    MC = "MC (%)",
    n = "n (abs)",
    hi = "hi (%)",
    Ni_asc = "Ni (↑)",
    Hi_asc = "Hi (↑)",
    Ni_desc = "Ni (↓)",
    Hi_desc = "Hi (↓)"
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black",
    row.striping.include_table_body = TRUE
  ) %>%
  sub_missing(
    columns = everything(),
    missing_text = "-" # Reemplaza los molestos NA por guiones limpios y estéticos
  )

# Renderizar la tabla en el reporte
tabla_sturges_f_gt
Tabla N° 2
Distribución de frecuencias para concentraciones de Flúor (F_pct_ISE_Fuse)
mediante Regla de Sturges
Clase Linf (%) Lsup (%) MC (%) n (abs) hi (%) Ni (↑) Hi (↑) Ni (↓) Hi (↓)
1 0.016 0.759 0.387 16 76.19 16 76.19 21 100.00
2 0.759 1.502 1.130 1 4.76 17 80.95 5 23.81
3 1.502 2.244 1.873 2 9.52 19 90.48 4 19.05
4 2.244 2.987 2.616 1 4.76 20 95.24 2 9.52
5 2.987 3.730 3.359 1 4.76 21 100.00 1 4.76
TOTALES - - - 21 100.00 - 100.00 - 100.00
Autores: Grupo 1
Semestre 2026 - 2026

HISTOGRAMA MEJORADO DE LA VARIABLE

#----------------------- PREPARACIÓN DE DATOS (Flúor) -----------------------
# Filtramos los NAs y números negativos
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))
FLUOR <- datos$F_pct_ISE_Fuse[!is.na(datos$F_pct_ISE_Fuse) & datos$F_pct_ISE_Fuse >= 0]

# Definimos intervalos manuales adaptados al Flúor
# Calcula el techo máximo y define si va de 1 en 1 o de 2 en 2 para que sea limpio
max_f <- ceiling(max(FLUOR))
paso <- ifelse(max_f > 15, 2, 1) 
breaks_entero <- seq(0, max_f, by = paso)

# Cálculo de la tabla de frecuencias para extraer los datos
h_data <- hist(FLUOR, breaks = breaks_entero, plot = FALSE)
MC <- h_data$mids
Ni_asc <- cumsum(h_data$counts)
Ni_desc <- rev(cumsum(rev(h_data$counts)))

#----------------------- 1. HISTOGRAMA MEJORADO -----------------------
# Aumentamos margen superior para que el título y los números tengan espacio
par(mar=c(5, 5, 5, 2))

h_plot <- hist(FLUOR, breaks = breaks_entero,
               main = "Gráfica 3: Distribución del Contenido de Flúor (%)",
               xlab = "Contenido de Flúor (%)",
               ylab = "Frecuencia (Cantidad)",
               col = "thistle", border = "purple4", # Paleta morada adaptada al Flúor
               xaxt = "n",  # Quitamos eje X para poner números enteros
               las = 1,
               ylim = c(0, max(h_data$counts) * 1.15)) # Espacio dinámico para las etiquetas

# Eje X con números enteros claros
axis(1, at = breaks_entero, labels = breaks_entero, font = 2)

# Etiquetas con los valores exactos encima de las barras
text(h_plot$mids, h_plot$counts, labels = h_plot$counts,
     adj = c(0.5, -0.5), cex = 0.9, font = 2, col = "black")

ANÁLISIS VISUAL ACUMULADO: OJIVA ASCENDENTE Y DESCENDENTE

#----------------------- 2. OJIVA INTEGRADA Y PROFESIONAL (Flúor) -----------------------
# Restauramos los márgenes a la normalidad ya que pondremos la leyenda adentro
par(mar=c(5, 5, 4, 2))

plot(MC, Ni_asc,
     main = "Gráfica 4: Ojiva Acumulada de Frecuencias de Flúor (ni)",
     xlab = "Contenido de Flúor (%)",
     ylab = "Frecuencia Acumulada (N muestras)",
     type = "b", pch = 19, col = "darkmagenta", lwd = 3,
     xaxt = "n", las = 1,
     ylim = c(0, max(Ni_asc) * 1.05),
     panel.first = grid(nx = NULL, ny = NULL, col = "gray90")) # Rejilla de fondo

# Segunda línea (Descendente)
lines(MC, Ni_desc, type = "b", pch = 17, col = "darkorange", lwd = 3, lty = 2)

# Eje X con los intervalos exactos (usando la variable breaks_entero calculada previamente)
axis(1, at = breaks_entero, labels = breaks_entero)

# Leyenda reubicada en el espacio vacío del lado derecho para una estética limpia
legend("right",
       legend = c("Acumulada Menor que (Ascendente)", "Acumulada Mayor que (Descendente)"),
       col = c("darkmagenta", "darkorange"),
       lty = c(1, 2),
       pch = c(19, 17),
       lwd = 2,
       title = "Tipo de Ojiva",
       bty = "n",  # Sin caja de borde para que se fusione con el fondo
       cex = 0.85) # Tamaño de letra ajustado

#----------------------- 2. OJIVA PROFESIONAL FLÚOR - EN PORCENTAJES (Hi) -----------------------

# 1. FILTRADO DE SEGURIDAD: Evitamos que la fila de TOTALES cause conflicto de longitudes
# Nos aseguramos de tomar únicamente las clases numéricas reales (sin el NA de totales)
MC_graficar_f       <- MC[!is.na(MC)]
Hi_asc_graficar_f   <- Hi_asc[1:length(MC_graficar_f)]
Hi_desc_graficar_f  <- Hi_desc[1:length(MC_graficar_f)]

# Definimos los cortes del eje X uniendo el límite inferior de cada clase y el último superior
breaks_f <- c(liminf[!is.na(liminf)], limsup[length(limsup) - 1])

# 2. Restauramos los márgenes a la normalidad (la leyenda se acomoda adentro)
par(mar=c(5, 5, 4, 2))

# 3. Graficar curva ascendente usando los porcentajes (Hi_asc) corregidos
plot(MC_graficar_f, Hi_asc_graficar_f,
     main = "Gráfica 5: Ojiva Acumulada de Frecuencias de Flúor (hi)",
     xlab = "Concentración de Flúor - F (%)",
     ylab = "Frecuencia Relativa Acumulada (%)",
     type = "b", pch = 19, col = "darkmagenta", lwd = 3,
     xaxt = "n", las = 1,
     ylim = c(0, 105), # Escala porcentual fija hasta 105% para dar aire arriba
     panel.first = grid(nx = NULL, ny = NULL, col = "gray90")) # Rejilla de fondo

# 4. Segunda línea descendente usando los porcentajes (Hi_desc)
lines(MC_graficar_f, Hi_desc_graficar_f, type = "b", pch = 17, col = "darkorange", lwd = 3, lty = 2)

# 5. Dibujar el Eje X con los intervalos exactos de Sturges (redondeados a 2 decimales para estética)
axis(1, at = breaks_f, labels = round(breaks_f, 2), cex.axis = 0.8)

# 6. Leyenda técnica reubicada en el espacio vacío del lienzo
legend("right",
       legend = c("Acumulada Menor que (Ascendente %)", "Acumulada Mayor que (Descendente %)"),
       col = c("darkmagenta", "darkorange"),
       lty = c(1, 2),
       pch = c(19, 17),
       lwd = 2,
       title = "Tipo de Ojiva",
       bty = "n",  # Sin borde para integrarse al fondo
       cex = 0.85)

ANÁLISIS VISUAL POR RANGOS DE F_pct_ISE_Fuse

#----------------------- PREPARACIÓN DE DATOS (Flúor) -----------------------
# Limpieza de comas y exclusión de negativos y NAs
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))
F_VAR <- datos$F_pct_ISE_Fuse[!is.na(datos$F_pct_ISE_Fuse) & datos$F_pct_ISE_Fuse >= 0]

#----------------------- CÁLCULO DE INTERVALOS (STURGES) -----------------------
# Calculamos matemáticamente las clases y la amplitud
k <- floor(1 + 3.322 * log10(length(F_VAR)))
R_rango <- max(F_VAR) - min(F_VAR)
A_amplitud <- R_rango / k

# Generamos los cortes exactos de Sturges
breaks_f <- seq(from = min(F_VAR), by = A_amplitud, length.out = k + 1)

# Calculamos el histograma de forma invisible
h_info <- hist(F_VAR, breaks = breaks_f, plot = FALSE, right = FALSE)

# Creamos las etiquetas para la leyenda (redondeadas a 2 decimales para la estética)
intervalos <- paste0("[", round(h_info$breaks[-length(h_info$breaks)], 2), 
                     " - ", round(h_info$breaks[-1], 2), ")")

# Paleta viva (Rainbow ajustada)
colores_hist <- rainbow(length(h_info$counts), start = 0.75, end = 0.95)

#----------------------- HISTOGRAMA Y LEYENDA CORREGIDA -----------------------
# AQUÍ ESTÁ EL CAMBIO 1: Aumentamos el margen derecho de 8 a 12
par(mar=c(5, 5, 5, 12), xpd=TRUE)

hist(F_VAR, breaks = breaks_f,
     main = "Gráfica 6: Distribución de F_pct_ISE_Fuse",
     xlab = "Contenido de Flúor (%)",
     ylab = "Frecuencia (Cantidad)",
     col = colores_hist,
     border = "white",
     labels = TRUE,    
     right = FALSE,
     las = 1,
     xaxt = "n",       
     ylim = c(0, max(h_info$counts) * 1.15)) 

# Eje X dinámico
axis(1, at = breaks_f, labels = round(breaks_f, 2), font = 2)

# AQUÍ ESTÁ EL CAMBIO 2: Reducimos el inset de -0.35 a -0.25 para acercar la leyenda
legend("topright", inset=c(-0.25, 0),
       legend = intervalos,
       fill = colores_hist,
       title = "Intervalos (%)",
       cex = 0.85, bty = "n")

BOXPLOT

#----------------------- PREPARACIÓN DE DATOS (Flúor) -----------------------
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))
F_VAR <- datos$F_pct_ISE_Fuse[!is.na(datos$F_pct_ISE_Fuse) & datos$F_pct_ISE_Fuse >= 0]

#-----------------------  BOXPLOT: ANÁLISIS DE VALORES ATÍPICOS -----------------------
par(mar=c(5, 5, 4, 2))

stats_f <- boxplot.stats(F_VAR)
media_f  <- round(mean(F_VAR), 2)
mediana_f <- round(median(F_VAR), 2)
n_outliers <- length(stats_f$out)

boxplot(F_VAR, horizontal = TRUE, col = "thistle", border = "purple4",
        main = "Gráfica 7: Análisis de Valores Atípicos (Flúor)", 
        xlab = "Concentración de Flúor (%)",
        pch = 21, 
        bg = "red", 
        outcol = "darkred",
        yaxt = "n")

# Punto de la Media Real (Rombo Azul)
points(media_f, 1, col = "blue", pch = 18, cex = 2)

#----------------------- ETIQUETAS SEPARADAS VERTICALMENTE -----------------------

# La Media se queda arriba en su posición original
text(x = media_f, 
     y = 1.25, 
     labels = paste("Media:", media_f), 
     col = "blue", 
     font = 2, 
     cex = 0.9)

# La Mediana se desplaza hacia la derecha
text(x = 0.6, 
     y = 0.70, 
     labels = paste("Mediana:", mediana_f), 
     col = "purple4", 
     font = 2, 
     cex = 0.9)

# Leyenda de atípicos
legend("topright", 
       legend = paste("Atípicos detectados:", n_outliers),
       text.col = "darkred", 
       bty = "n", 
       cex = 0.9)

#----------------------- BOXPLOT: DISTRIBUCIÓN LIMPIA (FLÚOR) -----------------------
par(mar=c(5, 5, 4, 2))

boxplot(F_VAR, 
        horizontal = TRUE, 
        outline = FALSE, 
        col = "thistle", 
        border = "purple4",
        main = "Grafica 8: Distribución del Cuerpo Mineral (Sin Atípicos) - Flúor", 
        xlab = "Concentración de Flúor (%)", 
        ylim = c(0, 0.70), # definir la escala real de los datos
        yaxt = "n") 

# Agregar cuadrícula de fondo
grid(nx = NULL, 
     ny = NA, 
     col = "gray85", 
     lty = "dashed")

# Agregar el punto de la media real (Rombo Azul)
points(media_f, 1, 
       col = "blue", 
       pch = 18, 
       cex = 2)

#----------------------- UBICACIÓN DE ETIQUETAS MEJORADA -----------------------

# La media se dibuja arriba del rombo azul
text(x = media_f, 
     y = 1.25, 
     labels = paste("Media:", media_f), 
     col = "blue", 
     font = 2, 
     cex = 0.9)

# La mediana se desplaza a la derecha para no estorbar a la caja
text(x = 0.25, 
     y = 0.70, 
     labels = paste("Mediana:", mediana_f), 
     col = "purple4", 
     font = 2, 
     cex = 0.9)

RESUMEN DESCRIPTIVO

# Asegúrate de cargar las librerías al inicio del chunk
library(dplyr)
library(gt)
library(e1071) # Necesaria para el cálculo de Asimetría y Curtosis

#----------------------- ANÁLISIS ESTADÍSTICO F_pct_ISE_Fuse -----------------------

# 1. Preparación de la variable continua
# Usamos 'datos' en minúsculas para mantener consistencia con el entorno de trabajo
datos$F_pct_ISE_Fuse <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$F_pct_ISE_Fuse))))

# 2. Limpieza de valores nulos o negativos para análisis de Ley geoquímica
# Se incluye el cero (>= 0) para no omitir valores mínimos válidos en el balance estadístico
F_LIMPIA <- datos$F_pct_ISE_Fuse[!is.na(datos$F_pct_ISE_Fuse) & datos$F_pct_ISE_Fuse >= 0]

# 3. Cálculos estadísticos descriptivos consolidados
resumen_stats_F <- data.frame(
  Estadistico = c("Tamaño muestral (n)", 
                  "Mínimo (%)", 
                  "Máximo (%)", 
                  "Media (%)", 
                  "Mediana (%)",
                  "Desviación Estándar", 
                  "Coef. Variación (%)", 
                  "Asimetría", 
                  "Curtosis"),
  Valor = c(
    length(F_LIMPIA),
    min(F_LIMPIA),
    max(F_LIMPIA),
    mean(F_LIMPIA),
    median(F_LIMPIA),
    sd(F_LIMPIA),
    (sd(F_LIMPIA) / mean(F_LIMPIA)) * 100,
    skewness(F_LIMPIA, type = 2),
    kurtosis(F_LIMPIA)
  )
)

# 4. Redondeo técnico para presentación en el reporte (2 decimales)
resumen_stats_F$Valor <- round(resumen_stats_F$Valor, 2)

#----------------------- SALIDA ESTÉTICA CON 'gt' -----------------------
tabla_stats_f_gt <- resumen_stats_F %>%
  gt() %>%
  tab_header(
    title = md("**Tabla N° 3**"),
    subtitle = md("Estadística Descriptiva para Concentraciones de Flúor (F)")
  ) %>%
  tab_source_note(
    source_note = md("Autores: Grupo 1 <br> Semestre 2026 - 2026")
  ) %>%
  cols_label(
    Estadistico = "Parámetro Estadístico",
    Valor = "Resultado"
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black",
    row.striping.include_table_body = TRUE
  )

# Renderizar la tabla en el documento de RMarkdown
tabla_stats_f_gt
Tabla N° 3
Estadística Descriptiva para Concentraciones de Flúor (F)
Parámetro Estadístico Resultado
Tamaño muestral (n) 21.00
Mínimo (%) 0.02
Máximo (%) 3.73
Media (%) 0.60
Mediana (%) 0.09
Desviación Estándar 1.03
Coef. Variación (%) 171.07
Asimetría 1.97
Curtosis 1.80
Autores: Grupo 1
Semestre 2026 - 2026

CONCLUSIÓN

CONCLUSIÓN DE LA VARIABLE F_pct_ISE_Fuse

El análisis descriptivo de la variable flúor (F), basado en un tamaño muestral de 21 registros, muestra concentraciones entre un mínimo de 0.02% y un máximo de 3.73%, con una media de 0.60% y una mediana de 0.09%. El coeficiente de variación de 171.07% y la desviación estándar de 1.03 confirman una alta dispersión y heterogeneidad en la distribución del elemento. Finalmente, los índices de forma revelan una marcada asimetría positiva (1.97) y una curtosis de 1.80; este comportamiento es típico en geoquímica para elementos traza o guías, donde la mayoría de las muestras se concentran en leyes basales muy bajas (cercanas al cero), mientras que el promedio se ve fuertemente desplazado por anomalías puntuales de alta concentración.