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]
Se cargaron correctamente los datos de todas las variables
CONCENTRACIÓN DE BISMUTO (Bi_ppm_MS_ST)
# Cargar las librerías necesarias
library(dplyr)
library(gt)
#----------------------- PROCESAMIENTO Y LIMPIEZA TOTAL -----------------------
# Conversión estricta a numérico
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
# EL FILTRO DEFINITIVO: Solo tomamos datos entre 0.1 y 63.50 ppm (Rango exacto de Sturges)
bi_numerico <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0.1 & datos$Bi_ppm_MS_ST <= 63.5]
# Conteo de exclusiones: Agrupamos los NAs, los menores a 0.1 y LOS ATÍPICOS MAYORES A 63.5
n_sin_datos_bi <- sum(is.na(datos$Bi_ppm_MS_ST) | datos$Bi_ppm_MS_ST < 0.1 | datos$Bi_ppm_MS_ST > 63.5)
#----------------------- MATRIZ DE FRECUENCIAS BASE -----------------------
TDF_VALIDOS_BI <- as.data.frame(table(bi_numerico), stringsAsFactors = FALSE)
colnames(TDF_VALIDOS_BI) <- c("CATEGORIA", "ni")
TDF_VALIDOS_BI$CATEGORIA <- as.numeric(TDF_VALIDOS_BI$CATEGORIA)
TDF_VALIDOS_BI <- TDF_VALIDOS_BI[order(TDF_VALIDOS_BI$CATEGORIA), ]
# Totales absolutos garantizados para el balance
total_variable_bi <- sum(TDF_VALIDOS_BI$ni)
total_general_bi <- total_variable_bi + n_sin_datos_bi # Se mantiene en 1366
#----------------------- AGRUPACIÓN TOP 10 -----------------------
if(nrow(TDF_VALIDOS_BI) > 10) {
tabla_top_bi <- head(TDF_VALIDOS_BI, 10)
sum_otros_bi <- sum(TDF_VALIDOS_BI$ni[11:nrow(TDF_VALIDOS_BI)])
fila_otros_bi <- data.frame(CATEGORIA = "Otras Concentraciones", ni = sum_otros_bi)
tabla_final_base_bi <- rbind(tabla_top_bi, fila_otros_bi)
} else {
tabla_final_base_bi <- TDF_VALIDOS_BI
}
tabla_final_base_bi$CATEGORIA <- as.character(tabla_final_base_bi$CATEGORIA)
#----------------------- CÁLCULO DE PORCENTAJES (hi) -----------------------
tabla_final_base_bi$hi <- round((tabla_final_base_bi$ni / total_general_bi) * 100, 4)
#----------------------- CONSTRUCCIÓN DE FILAS DE BALANCE -----------------------
fila_total_var_bi <- data.frame(
CATEGORIA = "TOTAL VARIABLE (Bi)",
ni = total_variable_bi,
hi = round((total_variable_bi / total_general_bi) * 100, 4)
)
# Fila Sin Datos (ahora incluye los 200 atípicos excluidos)
fila_sin_datos_bi <- data.frame(
CATEGORIA = "Sin Datos",
ni = n_sin_datos_bi,
hi = round((n_sin_datos_bi / total_general_bi) * 100, 4)
)
# Fila Total General Absoluto
fila_total_general_bi <- data.frame(
CATEGORIA = "TOTAL GENERAL",
ni = total_general_bi,
hi = 100.0000
)
#----------------------- ENSAMBLE DE MATRIZ FINAL -----------------------
tabla_final_bi <- rbind(tabla_final_base_bi, fila_total_var_bi, fila_sin_datos_bi, fila_total_general_bi)
colnames(tabla_final_bi) <- c("Valor Bi (ppm)", "ni", "hi")
#----------------------- SALIDA ESTÉTICA CON GT -----------------------
tabla_bismuto_fija_gt <- tabla_final_bi %>%
gt() %>%
tab_header(
title = md("**Tabla N° 1**"),
subtitle = md("Distribución de frecuencias para concentraciones de Bismuto (Bi) <br> *(Sin atípicos > 63.50 ppm)*")
) %>%
tab_source_note(
source_note = md("Autores: Grupo 1 <br> Semestre 2026 - 2026")
) %>%
cols_label(
`Valor Bi (ppm)` = "Valor Bi (ppm)",
ni = "n (abs)",
hi = "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
)
tabla_bismuto_fija_gt
| Tabla N° 1 | ||
| Distribución de frecuencias para concentraciones de Bismuto (Bi) (Sin atípicos > 63.50 ppm) |
||
| Valor Bi (ppm) | n (abs) | hi (%) |
|---|---|---|
| 0.1 | 63 | 4.6120 |
| 0.2 | 94 | 6.8814 |
| 0.3 | 61 | 4.4656 |
| 0.4 | 46 | 3.3675 |
| 0.5 | 45 | 3.2943 |
| 0.6 | 40 | 2.9283 |
| 0.7 | 25 | 1.8302 |
| 0.8 | 27 | 1.9766 |
| 0.9 | 18 | 1.3177 |
| 1 | 20 | 1.4641 |
| Otras Concentraciones | 494 | 36.1640 |
| TOTAL VARIABLE (Bi) | 933 | 68.3016 |
| Sin Datos | 433 | 31.6984 |
| TOTAL GENERAL | 1366 | 100.0000 |
| Autores: Grupo 1 Semestre 2026 - 2026 |
||
ANÁLISIS DESCRIPTIVO Y AGRUPACIÓN EN CLASES (STRUGES) DE BISMUTO
# Cargar las librerías al inicio
library(dplyr)
library(gt)
#------------------------- PREPARACIÓN DE DATOS -------------------------
# Conversión a numérico (reemplazando comas por puntos y manejando advertencias)
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
# Creamos la variable de trabajo asegurando que los datos estén limpios desde el inicio
Bi_VAR <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0 & datos$Bi_ppm_MS_ST <= 65]
Bi_Limpio <- Bi_VAR
#------------------------- ANÁLISIS DE CONCENTRACIÓN (ESTADÍSTICOS) -------------------------
cat("\n=======================================================\n")
##
## =======================================================
cat("ANÁLISIS DE CONCENTRACIÓN (Bi_ppm_MS_ST):\n")
## ANÁLISIS DE CONCENTRACIÓN (Bi_ppm_MS_ST):
cat("La concentración promedio es: ", round(mean(Bi_VAR, na.rm = TRUE), 2), " ppm \n")
## La concentración promedio es: 6.46 ppm
cat("La concentración máxima detectada es: ", max(Bi_VAR, na.rm = TRUE), " ppm \n")
## La concentración máxima detectada es: 63.5 ppm
cat("Total de muestras analizadas: ", sum(!is.na(Bi_VAR)), " registros \n")
## Total de muestras analizadas: 933 registros
cat("=======================================================\n")
## =======================================================
#------------------------- TABLA DE FRECUENCIAS - STURGES -------------------------
# 1. Parámetros básicos: Rango, Número de clases (Sturges) y Amplitud
R <- max(Bi_Limpio) - min(Bi_Limpio)
k <- floor(1 + 3.322 * log10(length(Bi_Limpio)))
A <- R / k
# 2. Definición de límites y Marcas de Clase (MC)
liminf <- seq(from = min(Bi_Limpio), by = A, length.out = k)
limsup <- liminf + A
MC <- (liminf + limsup) / 2
# 3. Conteo de frecuencias por clase (n)
n <- numeric(k)
for (i in 1:k) {
if (i == k) {
n[i] <- sum(Bi_VAR >= liminf[i] & Bi_VAR <= limsup[i], na.rm = TRUE)
} else {
n[i] <- sum(Bi_VAR >= liminf[i] & Bi_VAR < 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 -------------------------
TablaBi_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 cierre de tabla y balance formal
fila_totales_Bi <- 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 total
TablaBi_Final <- rbind(TablaBi_Sturges, fila_totales_Bi)
#------------------------- MOSTRAR TABLA FINAL CON 'gt' -------------------------
tabla_sturges_bi_gt <- TablaBi_Final %>%
gt() %>%
tab_header(
title = md("**Tabla N° 2**"),
subtitle = md("Distribución de frecuencias para concentraciones de Bismuto (Bi) <br> mediante Regla de Sturges")
) %>%
tab_source_note(
source_note = md("Autores: Grupo 1 <br> Semestre 2026 - 2026")
) %>%
fmt_markdown(columns = Clase) %>% # Asegura que "**TOTALES**" se renderice en negrita
cols_label(
Clase = "Clase",
liminf = "Linf (ppm)",
limsup = "Lsup (ppm)",
MC = "MC (ppm)",
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 = "NA"
)
# Renderizar la tabla en el reporte
tabla_sturges_bi_gt
| Tabla N° 2 | |||||||||
| Distribución de frecuencias para concentraciones de Bismuto (Bi) mediante Regla de Sturges |
|||||||||
| Clase | Linf (ppm) | Lsup (ppm) | MC (ppm) | n (abs) | hi (%) | Ni (↑) | Hi (↑) | Ni (↓) | Hi (↓) |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 0.10 | 6.44 | 3.27 | 706 | 75.67 | 706 | 75.67 | 933 | 100.00 |
| 2 | 6.44 | 12.78 | 9.61 | 83 | 8.90 | 789 | 84.57 | 227 | 24.33 |
| 3 | 12.78 | 19.12 | 15.95 | 43 | 4.61 | 832 | 89.17 | 144 | 15.43 |
| 4 | 19.12 | 25.46 | 22.29 | 21 | 2.25 | 853 | 91.43 | 101 | 10.83 |
| 5 | 25.46 | 31.80 | 28.63 | 22 | 2.36 | 875 | 93.78 | 80 | 8.57 |
| 6 | 31.80 | 38.14 | 34.97 | 16 | 1.71 | 891 | 95.50 | 58 | 6.22 |
| 7 | 38.14 | 44.48 | 41.31 | 15 | 1.61 | 906 | 97.11 | 42 | 4.50 |
| 8 | 44.48 | 50.82 | 47.65 | 10 | 1.07 | 916 | 98.18 | 27 | 2.89 |
| 9 | 50.82 | 57.16 | 53.99 | 7 | 0.75 | 923 | 98.93 | 17 | 1.82 |
| 10 | 57.16 | 63.50 | 60.33 | 10 | 1.07 | 933 | 100.00 | 10 | 1.07 |
| TOTALES | NA | NA | NA | 933 | 100.00 | NA | 100.00 | NA | 100.00 |
| Autores: Grupo 1 Semestre 2026 - 2026 |
|||||||||
POLÍGONO DE FRECUENCIAS ABSOLUTAS DEL BISMUTO (Bi)
#----------------------- PROCESAMIENTO AUTOMÁTICO Bi_ppm_MS_ST -----------------------
# 1. Conversión de la variable a numérico y limpieza de datos (Bismuto)
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
# Excluimos NAs y limitamos al rango exacto de la tabla
BI_VALIDO <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0.1 & datos$Bi_ppm_MS_ST <= 63.5]
#----------------------- EXTRACCIÓN AUTOMÁTICA DE PARÁMETROS -----------------------
# 2. Replicamos las ecuaciones exactas de tu Tabla N° 2
R_bi <- max(BI_VALIDO) - min(BI_VALIDO)
k_bi <- floor(1 + 3.322 * log10(length(BI_VALIDO)))
A_bi <- R_bi / k_bi
# 3. Re-calculamos los límites e intervalos exactos
liminf_bi <- seq(from = min(BI_VALIDO), by = A_bi, length.out = k_bi)
limsup_bi <- liminf_bi + A_bi
# AUTOMATIZACIÓN 1: Cálculo de las Marcas de Clase (MC) reales de la tabla
mc_reales_bi <- (liminf_bi + limsup_bi) / 2
# AUTOMATIZACIÓN 2: Conteo iterativo automático por clases (para el ni)
n_vector <- numeric(k_bi)
for (i in 1:k_bi) {
if (i == k_bi) {
n_vector[i] <- sum(BI_VALIDO >= liminf_bi[i] & BI_VALIDO <= limsup_bi[i])
} else {
n_vector[i] <- sum(BI_VALIDO >= liminf_bi[i] & BI_VALIDO < limsup_bi[i])
}
}
# AUTOMATIZACIÓN 3: Cálculo funcional de la frecuencia relativa (hi %)
hi_porcentaje_bi <- (n_vector / sum(n_vector)) * 100
#----------------------- ANCLAJE A CERO CON MARCAS DE CLASE -----------------------
# 4. Creamos los extremos ficticios para el anclaje a cero usando la amplitud
mc_inicio_bi <- mc_reales_bi[1] - A_bi
mc_final_bi <- mc_reales_bi[length(mc_reales_bi)] + A_bi
# Unimos los vectores definitivos para el polígono
marcas_clase_bi <- c(mc_inicio_bi, mc_reales_bi, mc_final_bi)
frecuencias_hi_bi <- c(0, hi_porcentaje_bi, 0)
# El pico máximo se detecta de forma automática con max() (será 75.67%)
max_y_hi_bi <- max(frecuencias_hi_bi)
#----------------------- GRAFICAR POLÍGONO DE FRECUENCIAS (hi) -----------------------
# Margen inferior amplio (mar[1] = 6) para que las etiquetas verticales no se corten
par(mar = c(6, 5, 4, 2))
# 5. Inicializar el lienzo con el rango de marcas de clase real
plot(marcas_clase_bi, frecuencias_hi_bi,
type = "n",
main = "Gráfica 1: Polígono de Frecuencias Relativas de Bismuto (Bi)",
xlab = "Marcas de Clase - Concentración de Bi (ppm)",
ylab = "Frecuencia Relativa - hi (%)",
xlim = c(mc_inicio_bi, mc_final_bi),
ylim = c(0, max_y_hi_bi * 1.05),
xaxt = "n", yaxt = "n",
panel.first = grid(nx = NULL, ny = NULL, col = "gray90"))
# 6. Dibujar las líneas del polígono
lines(marcas_clase_bi, frecuencias_hi_bi, type = "l", col = "darkcyan", lwd = 3)
# Dibujar puntos estructurales SOLO en las marcas de clase reales (sin textos encima)
points(mc_reales_bi, hi_porcentaje_bi, pch = 19, col = "darkcyan", cex = 1.2)
# Relleno bajo la curva
polygon(marcas_clase_bi, frecuencias_hi_bi, col = rgb(0, 0.55, 0.55, 0.12), border = NA)
#----------------------- PERSONALIZACIÓN DE EJES CORREGIDOS -----------------------
# Eje X REPARADO: Imprime las Marcas de Clase correctas y las rota a vertical
axis(1, at = mc_reales_bi, labels = round(mc_reales_bi, 2), cex.axis = 0.75, las = 1)
# Eje Y: Valores horizontales mostrando porcentajes de guía y el pico máximo real
marcas_eje_y_bi <- seq(0, 70, by = 20)
axis(2, at = c(marcas_eje_y_bi, max_y_hi_bi),
labels = paste0(c(marcas_eje_y_bi, round(max_y_hi_bi, 2)), "%"),
las = 1, cex.axis = 0.8)
HISTOGRAMA DISTRIBUCIÓN DE BISMUTO
#----------------------- PROCESAMIENTO Bi_ppm_MS_ST -----------------------
# 1. Conversión de Bi_ppm_MS_ST a numérico (blindado contra comas y textos)
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
# Creamos variable de trabajo para las gráficas y FILTRAMOS negativos, NAs y atípicos (> 65)
Bi_VAR <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0 & datos$Bi_ppm_MS_ST <= 65]
#----------------------- TABLA DE FRECUENCIAS SIMPLIFICADA -----------------------
# Al ser continua, agrupamos por rangos automáticos (bins) para legibilidad
bi_simplificado <- 5
# Usamos pretty para obtener cortes redondeados y estéticos en ppm
breaks_s <- pretty(Bi_VAR, n = bi_simplificado)
# 2. Generación del Histograma
# Aplicamos la lógica a la variable de Bismuto
hist(Bi_VAR,
breaks = breaks_s,
main = "Gráfica 2: Distribución de Bi_ppm_MS_ST (Simplificada)",
xlab = "Concentración de Bi (ppm)",
ylab = "Cantidad de muestras",
col = "darkseagreen",
right = FALSE)
#----------------------- PREPARACIÓN DE DATOS (Bismuto) -----------------------
# Conversión y limpieza de la variable Bi_ppm_MS_ST
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
Bi_VAR <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0 & datos$Bi_ppm_MS_ST <= 65]
# Definimos exactamente 10 intervalos basados en números enteros
n_interv <- 10
min_bi <- floor(min(Bi_VAR))
max_bi <- ceiling(max(Bi_VAR))
# Generamos 11 puntos de corte para obtener 10 bins exactos
breaks_bi <- seq(min_bi, max_bi, length.out = n_interv + 1)
# Cálculo de datos para los gráficos
h_data_bi <- hist(Bi_VAR, breaks = breaks_bi, plot = FALSE)
intervalos_nombres <- paste0("[", round(h_data_bi$breaks[-length(h_data_bi$breaks)], 0),
"-", round(h_data_bi$breaks[-1], 0), "]")
MC_bi <- h_data_bi$mids
Ni_asc_bi <- cumsum(h_data_bi$counts)
Ni_desc_bi <- rev(cumsum(rev(h_data_bi$counts)))
#----------------------- GRÁFICO DE BARRAS PROFESIONAL (Bi) -----------------------
# Margen inferior amplio para las etiquetas de los intervalos
par(mar=c(7, 5, 5, 2))
# Paleta de colores: 10 colores diferenciados
colores_bi <- terrain.colors(n_interv)
h_plot_bi <- barplot(h_data_bi$counts,
names.arg = intervalos_nombres,
main = "Gráfica 3: Distribución de Bismuto por Rangos (10 Intervalos)",
xlab = "Rangos de Concentración (ppm)",
ylab = "Frecuencia (N° de muestras)",
col = colores_bi,
border = "white",
las = 1,
cex.names = 0.8,
ylim = c(0, max(h_data_bi$counts) * 1.2))
# Valores exactos sobre las barras
text(x = h_plot_bi, y = h_data_bi$counts, labels = h_data_bi$counts,
pos = 3, cex = 0.9, font = 2, col = "darkblue")
OJIVAS ni Y hi
#----------------------- OJIVA INTEGRADA Y PROFESIONAL (Bismuto) -----------------------
# 1. Construimos los cortes exactos del eje X
cortes_eje_x_bi <- c(liminf, limsup[length(limsup)])
# Restauramos los márgenes a la normalidad
par(mar=c(5, 5, 4, 2))
plot(MC, Ni_asc,
main = "Gráfica 4: Ojiva Acumulada de Frecuencias de Bismuto (ni)",
xlab = "Concentración de Bismuto (ppm)",
ylab = "Frecuencia Acumulada (N muestras)",
type = "b", pch = 19, col = "forestgreen", 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
# Línea descendente
lines(MC, Ni_desc, type = "b", pch = 17, col = "firebrick", lwd = 3, lty = 2)
# Eje X con los cortes de los intervalos exactos
axis(1, at = cortes_eje_x_bi, labels = round(cortes_eje_x_bi, 2), cex.axis = 0.8)
# Leyenda
legend("right",
legend = c("Acumulada Menor que (Ascendente)", "Acumulada Mayor que (Descendente)"),
col = c("forestgreen", "firebrick"),
lty = c(1, 2),
pch = c(19, 17),
lwd = 2,
title = "Tipo de Ojiva",
bty = "n", # Sin caja de borde
cex = 0.85)
#----------------------- OJIVA PROFESIONAL EN PORCENTAJES (Bi) - FRECUENCIAS RELATIVAS ---------
# Restauramos los márgenes a la normalidad
par(mar=c(5, 5, 4, 2))
plot(MC, Hi_asc,
main = "Gráfica 5: Ojiva Acumulada de Frecuencias de Bismuto (hi)",
xlab = "Concentración de Bismuto (ppm)",
ylab = "Frecuencia Relativa Acumulada (%)",
type = "b", pch = 19, col = "forestgreen", 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
# Línea descendente
lines(MC, Hi_desc, type = "b", pch = 17, col = "firebrick", lwd = 3, lty = 2)
# Eje X con los cortes de los intervalos exactos
axis(1, at = cortes_eje_x_bi, labels = round(cortes_eje_x_bi, 2), cex.axis = 0.8)
# Leyenda adaptada a porcentajes
legend("right",
legend = c("Acumulada Menor que (Ascendente %)", "Acumulada Mayor que (Descendente %)"),
col = c("forestgreen", "firebrick"),
lty = c(1, 2),
pch = c(19, 17),
lwd = 2,
title = "Tipo de Ojiva",
bty = "n",
cex = 0.85)
BOXPLTS DE VALORES ATÍPICOS Y DISTRIBUCIÓN LIMPIA
#----------------------- BOXPLOT: ANÁLISIS DE VALORES ATÍPICOS -----------------------
par(mar=c(5, 6, 5, 2), xpd = FALSE)
# Cálculos estadísticos previos
stats_bi <- boxplot.stats(Bi_VAR)
media_bi <- round(mean(Bi_VAR), 2)
mediana_bi <- round(median(Bi_VAR), 2)
n_outliers <- length(stats_bi$out)
# Generación del Boxplot
boxplot(Bi_VAR, horizontal = TRUE, col = "#DCE775", border = "#33691E",
main = "Gráfica 6: Análisis de Valores Atípicos (Bismuto)",
xlab = "Concentración de Bi (ppm)",
pch = 21,
bg = "red",
col.outline = "darkred",
frame = FALSE)
# Punto de Media y etiquetas de texto mejor ubicadas
points(media_bi, 1,
col = "blue",
pch = 18,
cex = 2)
text(media_bi, 1.25,
labels = paste("Media:", media_bi),
col = "blue",
font = 2,
cex = 0.9)
text(mediana_bi, 0.75,
labels = paste("Mediana:", mediana_bi),
col = "#1B5E20",
font = 2,
cex = 0.9)
# Leyenda (corregida para evitar errores de sintaxis)
legend("topright",
legend = paste("Atípicos detectados:", n_outliers),
pch = 21,
pt.bg = "red",
bty = "n",
text.col = "darkred",
cex = 0.9)
#----------------------- BOXPLOT: DISTRIBUCIÓN LIMPIA (CUERPO MINERAL) -----------------------
par(mar=c(5, 6, 5, 2))
# Generación del Boxplot sin valores atípicos (outline = FALSE)
boxplot(Bi_VAR,
horizontal = TRUE,
outline = FALSE,
col = "#81D4FA",
border = "#01579B",
main = "Gráfica 7: Distribución del Cuerpo Mineral (Sin Atípicos)",
xlab = "Concentración de Bi (ppm)",
frame = FALSE)
# Agregar cuadrícula de fondo
grid(nx = NULL,
ny = NA,
col = "gray85",
lty = "dashed")
# Valores sobre la vista limpia
points(media_bi, 1,
col = "#E65100",
pch = 18,
cex = 2)
text(media_bi, 1.25,
labels = paste("Media:", media_bi),
col = "#BF360C",
font = 2,
cex = 0.9)
text(mediana_bi, 0.75,
labels = paste("Mediana:", mediana_bi),
col = "#01579B",
font = 2,
cex = 0.9)
HISTOGRAMA CON BOXPLOT FLOTANTE (BISMUTO)
#----------------------- PREPARACIÓN DE DATOS -----------------------
# Conversión y limpieza de la variable Bi_ppm_MS_ST
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
Bi_VAR <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0 & datos$Bi_ppm_MS_ST <= 65]
# Definimos exactamente 10 intervalos basados en números enteros
n_interv <- 10
min_bi <- floor(min(Bi_VAR))
max_bi <- ceiling(max(Bi_VAR))
breaks_bi <- seq(min_bi, max_bi, length.out = n_interv + 1)
#----------------------- CÁLCULO DEL HISTOGRAMA (INVISIBLE) -----------------------
# Calculamos el histograma internamente para extraer datos
hist_pro_bi <- hist(Bi_VAR, breaks = breaks_bi, plot = FALSE, right = FALSE)
max_y_bi <- max(hist_pro_bi$counts)
#----------------------- CÁLCULO DEL RANGO X TOTAL (CORRECCIÓN) -----------------------
# Calculamos el rango necesario para abarcar tanto las barras como los atípicos
xlim_range <- range(c(Bi_VAR, breaks_bi))
# Aseguramos márgenes, con espacio ampliado a la derecha para la leyenda lateral
par(mar = c(5, 5, 4, 12), xpd = TRUE)
#----------------------- GRÁFICA INTEGRADA (HISTOGRAMA) -----------------------
# 1. Dibujamos el histograma base usando tu paleta terrain.colors
colores_bi <- terrain.colors(n_interv)
hist(Bi_VAR,
breaks = breaks_bi,
col = colores_bi,
border = "white",
main = "Gráfica 8: Distribución de Bismuto con Boxplot Interno",
xlab = "Concentración de Bi (ppm)",
ylab = "Frecuencia (Cantidad)",
xlim = xlim_range, # Asegura que todo el eje X sea visible
ylim = c(0, max_y_bi * 1.15), # Añadimos espacio extra en la parte superior
las = 1,
labels = TRUE, # Muestra los números encima de las barras
right = FALSE,
xaxt = "n") # Suprime el eje X por defecto
# 2. Personalización del eje X dinámico (breaks exactos)
axis(1, at = breaks_bi, labels = round(breaks_bi, 1), font = 2, cex.axis = 0.7)
# 3. Superponemos el Boxplot directamente
boxplot(Bi_VAR,
horizontal = TRUE,
add = TRUE, # Superpone la gráfica
axes = FALSE, # Oculta ejes
at = max_y_bi / 2, # Altura de flotación (mitad del eje Y)
boxwex = max_y_bi / 3, # Grosor de la caja
col = adjustcolor("#DCE775", alpha.f = 0.7), # Color verde con 70% de opacidad
border = "#33691E", # Borde verde oscuro
lwd = 1.5,
pch = 21, bg = "red", # Estilo de atípicos en rojo
outcol = "darkred") # Borde de los puntos atípicos
# 4. Añadimos la leyenda lateral
intervalos_bi <- paste0("[", round(hist_pro_bi$breaks[-length(hist_pro_bi$breaks)], 1),
" - ", round(hist_pro_bi$breaks[-1], 1), ")")
legend("topright", inset=c(-0.35, 0),
legend = intervalos_bi,
fill = colores_bi,
title = "Intervalos (ppm)",
cex = 0.8, bty = "n")
INDICADORES ESTADÍSTICOS
# Cargar las librerías al inicio
library(dplyr)
library(gt)
library(e1071) # Necesaria para Asimetría y Curtosis
#----------------------- ANÁLISIS ESTADÍSTICO Bi_ppm_MS_ST -----------------------
# 0. Limpieza automática de nombres (elimina espacios en blanco accidentales)
colnames(datos) <- trimws(colnames(datos))
# 1. Preparación de la variable con validación de existencia
if("Bi_ppm_MS_ST" %in% colnames(datos)) {
# Conversión a numérico (manejo de comas decimales y supresión de advertencias)
datos$Bi_ppm_MS_ST <- suppressWarnings(as.numeric(gsub(",", ".", as.character(datos$Bi_ppm_MS_ST))))
# 2. Limpieza de valores nulos, trazas invisibles y atípicos extremos
# EL CORTE EXACTO: >= 0.1 y <= 65 para mantener la armonía de 933 datos con la Tabla de Sturges
Bi_LIMPIA <- datos$Bi_ppm_MS_ST[!is.na(datos$Bi_ppm_MS_ST) & datos$Bi_ppm_MS_ST >= 0.1 & datos$Bi_ppm_MS_ST <= 65]
# 3. Cálculos estadísticos descriptivos
resumen_stats_Bi <- data.frame(
Estadistico = c("Tamaño muestral (n)",
"Mínimo (Min)",
"Máximo (Max)",
"Media (x̅)",
"Mediana (Me)",
"Desviación Estándar (s)",
"Coef. Variación (CV)",
"Asimetría (As)",
"Curtosis (k)"),
Valor = c(
length(Bi_LIMPIA),
min(Bi_LIMPIA),
max(Bi_LIMPIA),
mean(Bi_LIMPIA),
median(Bi_LIMPIA),
sd(Bi_LIMPIA),
(sd(Bi_LIMPIA) / mean(Bi_LIMPIA)) * 100,
skewness(Bi_LIMPIA, type = 2),
kurtosis(Bi_LIMPIA)
)
)
# 4. Redondeo técnico a dos decimales para el reporte
resumen_stats_Bi$Valor <- round(resumen_stats_Bi$Valor, 2)
#----------------------- SALIDA ESTÉTICA CON 'gt' -----------------------
tabla_stats_bi_gt <- resumen_stats_Bi %>%
gt() %>%
tab_header(
title = md("**Tabla N° 3**"),
subtitle = md("Estadística Descriptiva para Concentraciones de Bismuto (Bi)")
) %>%
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 final
tabla_stats_bi_gt
} else {
stop("¡ERROR! La columna 'Bi_ppm_MS_ST' no existe en el dataset. Verifique el nombre en su archivo de origen.")
}
| Tabla N° 3 | |
| Estadística Descriptiva para Concentraciones de Bismuto (Bi) | |
| Parámetro Estadístico | Resultado |
|---|---|
| Tamaño muestral (n) | 933.00 |
| Mínimo (Min) | 0.10 |
| Máximo (Max) | 63.50 |
| Media (x̅) | 6.46 |
| Mediana (Me) | 1.30 |
| Desviación Estándar (s) | 11.95 |
| Coef. Variación (CV) | 184.99 |
| Asimetría (As) | 2.69 |
| Curtosis (k) | 7.08 |
| Autores: Grupo 1 Semestre 2026 - 2026 |
|
CONCLUSIÓN DE LA VARIABLE Bi_ppm_MS_ST
El análisis de 933 muestras revela un rango de concentración entre 0.10 ppm y 63.50 ppm. El depósito presenta una media de 6.46 ppm y una mediana de 1.30 ppm, reflejando una fuerte heterogeneidad y dispersión de las leyes debido a una desviación estándar de 11.95 y un coeficiente de variación de 184.99%. Finalmente, los índices de forma confirman una marcada asimetría positiva de 2.69 y una curtosis de 7.08; esto demuestra matemáticamente que el yacimiento está dominado por concentraciones basales bajas, pero el promedio se ve fuertemente traccionado por anomalías puntuales de alta ley.