Codea Blog  

Blog Details

ANÁLISIS EXPLORATORIO DE DATOS: PRODUCCIÓN MINERA EN PERÚ 2020 - 2024

ANÁLISIS EXPLORATORIO DE DATOS: PRODUCCIÓN MINERA EN PERÚ 2020 - 2024

Por: Danny Turpo Condori

 

INTRODUCCION

Los procesos mineros se caracterizan por su complejidad y estar sujetas a una gran cantidad de variables (geológicas, logísticas, económicas, ambientales, por citar algunos ejemplos). El gran volumen de datos que se genera en estos procesos son un recurso importante que impulsa la toma de decisiones, optimizar procesos como los de extracción, predecir y prevenir fallas, identificar áreas de riesgo, y más.

Por lo que resulta importante conocer como realizar un correcto tratamiento y análisis de los datos con las diversas herramientas que tenemos en la actualidad, para poder tratar el gran volumen de información producida y de esta forma poder tomar las decisiones informadas.

Para este artículo se hace uso de herramientas especializadas en el análisis de datos de Python, se explora en una primera parte el proceso de manipulación de archivos centrándonos en la extracción de la información y las modificaciones necesarias paso a paso para la correcta lectura de los datos, y en una segunda parte dedicada en el análisis y visualización.

Los datos que se usaron en este articulo presentan los reportes de produccion de los principales recursos minerales metalicos, no metalicos y carboniferos que se extraen en el Peru, se pueden encontrar en el siguiente enlace: Data Produccion.

 

PRIMERA PARTE: MANIPULACION DE LOS ARCHIVOS Y EXTRACCIÓN DE LA INFORMACIÓN

El notebook desarrollado lo puedes encontrar en: Notebook

Se descarga la data correspondiente al periodo de años 2020 - 2024, y se procede a realizar una revisión visual en este caso archivos excel.

 

Figura 1. Archivos excels

 

Los archivos excel se dividen en Producción carbonífera, Producción metálica y Producción no metálica, de forma similar en cada año.

Figura 2. Revisión parte superior del excel

 

Figura 3. Revisión parte inferior del excel

 

Todos los archivos excel presentan una estructura similar a la que se muestra en las imágenes, teniendo un título y comentarios al final de la data que no son necesarios en este análisis.

Nuestro primer paso es conocer los archivos con los que vamos a trabajar para esto se utiliza la siguiente función que tiene como objetivo leer todos los archivos excel (.xlsx o .xls) dentro de una carpeta y subcarpetas, y cada uno de los archivos leídos son almacenados en un diccionario de DataFrame, asignando a cada uno al inicio del nombre el año al que corresponde.

 

Python

Copy code



def leer_archivos_excel(ruta_carpeta):
    dataframes_excel = {}
    nombres_dataframes = []

    for ruta, carpetas, archivos in os.walk(ruta_carpeta):
        _, anio = os.path.split(ruta)
        for archivo in archivos:
            if archivo.lower().endswith('.xlsx') or archivo.lower().endswith('.xls'):
                ruta_completa = os.path.join(ruta, archivo)
            
                df = pd.read_excel(ruta_completa)
                nombre_archivo, extension = os.path.splitext(archivo)
                nombre_df = f"df_{anio}_{nombre_archivo}" 
                i = 1
                nombre_temporal = nombre_df
                while nombre_temporal in nombres_dataframes:
                    nombre_temporal = f"{nombre_df}_{i}"
                    i += 1
                nombre_df = nombre_temporal               
                dataframes_excel[nombre_df] = df
                nombres_dataframes.append(nombre_df)

    return dataframes_excel, nombres_dataframes

    

 Al correr la función se obtiene el siguiente resultado:

 

Figura 4. DataFrames generados a partir de los excels.

 

Luego creamos variables a partir del diccionario de DataFrames usando los nombres contenidos en el diccionario, también se elimina los caracteres especiales y reemplaza espacios en blanco por sub guiones para tener nombres de variables válidos para Python.

 

Python

Copy code



# Crear las variables dinámicamente
dataframes_variables = {}

for nombre_df in nombres:

    nombre_variable = re.sub(r'\W+', '', nombre_df).replace(' ', '_')
    exec(f"{nombre_variable} = dataframes['{nombre_df}']")
    dataframes_variables[nombre_variable] = locals()[nombre_variable]

# Mostrar los nombres de las variables creadas
print("Nombres de las variables creadas:")
for nombre_variable in dataframes_variables:
    print(nombre_variable)

    

Se generan lo siguientes nuevos nombres:

 

Figura 5. Nuevos nombres asignados a los DataFrames.

 

De esta forma podemos acceder a cada archivo excel como un DataFrame. El siguiente paso es eliminar el título y comentarios que se encontraban en cada excel, ya que estos también fueron considerados en el DataFrame creado. Para realizarlo se puede hacer lo siguiente, que tome en cuenta sólo las filas que contengan los nombres de los minerales (considerar que los excel de producción carbonífera, metalica y no metalica tienen una lista de minerales diferentes cada una). Tomando como ejemplo el DataFrame “df_2022_ProduccionmetalicaEneDic2022” la columna 0 contiene los nombres de los minerales, pero esto puede variar en los otros DataFrame por lo que se debe considerar. Se toma en cuenta los valores únicos de la primera columna, considerando solo los minerales, estos nombres de minerales obtenidos se los asigna a una lista, también se debe considerar que hay minerales que están escrito de dos formas con tilde y sin tilde, para tratar estos datos se usa el estándar unicode.

 

Una vez se tenga la lista de nombres de minerales, se realiza lo siguiente, a cada DataFrame (según el tipo de mineral) se le pasa la lista de minerales correspondiente, se itera todas las filas y columnas del DataFrame y a la primera coincidencia con lista de nombre de minerales, asigna a la fila que se encontró como punto de inicio, la fila anterior se considera como los encabezados de la columna (o nombre de variable), el resto de filas superiores son eliminadas y se restablece el índice. El mismo procedimiento es realizado para eliminar los comentarios que se encuentran en la parte inferior de la tabla de datos.

 

Python

Copy code



def eliminar_filas_superiores(df, lista_minerales):
    fila_inicio = None

    # Iterar sobre todas las filas y columnas del DataFrame
    for indice_fila, fila in df.iterrows():
        for indice_columna, valor in fila.items():
            # Verificar si el valor coincide con la lista
            if valor in lista_minerales:
                fila_inicio = indice_fila
                break
        if fila_inicio is not None:
            break

    # Si no se encuentra ninguna coincidencia, no se hace nada
    if fila_inicio is None:
        return df

    nombres_columnas = df.iloc[fila_inicio - 1].tolist()
    df.columns = nombres_columnas
    df = df.iloc[fila_inicio:]
    df.reset_index(drop=True, inplace=True)

    return df


def eliminar_filas_inferiores(df, lista_minerales):
    fila_inicio = None

    for indice_fila, fila in reversed(list(df.iterrows())):
        for indice_columna, valor in fila.items():
            # Verificar si el valor coincide con la lista
            if valor in lista_minerales:
                fila_inicio = indice_fila
                break
        if fila_inicio is not None:
            break

    # Si no se encuentra ninguna coincidencia, no se hace nada
    if fila_inicio is None:
        return df

    df = df.iloc[:fila_inicio + 1]
    df.reset_index(drop=True, inplace=True)

    return df

    

Luego de obtener los DataFrame con la data importante, se procede a unir los DataFrame según el mineral de produccion (metalico, no metalico y carbonifero), para esto en cada DataFrame se crea una columna nueva llamada año en donde se indica el año de lectura de la producción, para no mezclar esta información cuando se una los datos. También se debe ordenar las columnas en un orden en concreto para que no ocurra errores al unir, esto implica que los nombres de las columnas de todos los archivos deben coincidir, en este caso los nombres de las columnas meses no coinciden en todas. Al finalizar se genera un nuevo excel y un archivo csv con toda la información correspondiente a cada tipo de producto que se produce.

 

Python

Copy code



df_ExtraccioncarboniferaEneFeb2024["AÑO"] = 2024
df_ExtraccioncarboniferaEneDic2023["AÑO"] = 2023
df_ExtraccioncarboniferaEneDic2022["AÑO"] = 2022
df_ExtraccioncarboniferaEneDic2021["AÑO"] = 2021
df_ProduccioncarboniferaEneDic2020["AÑO"] = 2020

# Lista de nombres de DataFrames de carboníferas
dataframes_nombres_carb = [
    'df_ExtraccioncarboniferaEneFeb2024',
    'df_ExtraccioncarboniferaEneDic2023',
    'df_ExtraccioncarboniferaEneDic2022',
    'df_ExtraccioncarboniferaEneDic2021',
    'df_ProduccioncarboniferaEneDic2020'
]

# Mostrar nombres de columnas para cada DataFrame
for df_nombre in dataframes_nombres_carb:
    print(f"Nombres de columnas para {df_nombre}:")
    print(eval(df_nombre).columns)
    print("\n")

# reordenando el orden de las columnas
orden_columnas = ['PRODUCTO', 'ESTRATO', 'TITULAR', 'UNIDAD', 'REGIÓN', 'PROVINCIA', 'DISTRITO',
       'ENERO', 'FEBRERO', 'MARZO', 'ABRIL', 'MAYO', 'JUNIO',
       'JULIO', 'AGOSTO', 'SEPTIEMBRE', 'OCTUBRE', 'NOVIEMBRE', 'DICIEMBRE',
       'ACUM. ENE-DIC', 'AÑO']

nuevos_nombres_columnas = {'ENERO': 'ENE', 'FEBRERO': 'FEB',
    'MARZO': 'MAR', 'ABRIL': 'ABR', 'MAYO': 'MAY',
    'JUNIO': 'JUN', 'JULIO': 'JUL', 'AGOSTO': 'AGO',
    'SEPTIEMBRE': 'SET', 'OCTUBRE': 'OCT', 'NOVIEMBRE': 'NOV',
    'DICIEMBRE': 'DIC', 'REGIÓN': 'DEPARTAMENTO'
}

posicion_columna = 19
nombre_acumulado = "VALOR ACUMULADO"
df_ExtraccioncarboniferaEneFeb2024.columns.values[posicion_columna] = nombre_acumulado
df_ExtraccioncarboniferaEneDic2023.columns.values[posicion_columna] = nombre_acumulado
df_ExtraccioncarboniferaEneDic2022.columns.values[posicion_columna] = nombre_acumulado

df_ExtraccioncarboniferaEneDic2021 = df_ExtraccioncarboniferaEneDic2021[orden_columnas]
df_ExtraccioncarboniferaEneDic2021 = df_ExtraccioncarboniferaEneDic2021.rename(columns=nuevos_nombres_columnas)
df_ExtraccioncarboniferaEneDic2021.columns.values[posicion_columna] = nombre_acumulado

df_ProduccioncarboniferaEneDic2020 = df_ProduccioncarboniferaEneDic2020[orden_columnas]
df_ProduccioncarboniferaEneDic2020 = df_ProduccioncarboniferaEneDic2020.rename(columns=nuevos_nombres_columnas)
df_ProduccioncarboniferaEneDic2020.columns.values[posicion_columna] = nombre_acumulado

# Lista para almacenar los DataFrames
dataframes = []

# Carga los DataFrames de la lista de nombres
for nombre_df in dataframes_nombres_carb:
    df = globals()[nombre_df]
    dataframes.append(df)

# Concatena los DataFrames
df_final = pd.concat(dataframes, ignore_index=True)

# Exporta el DataFrame resultante a un archivo CSV
df_final.to_csv('datos_combinados_produccioncarbonifera.csv', index=False)

# Exporta el DataFrame resultante a un archivo Excel
df_final.to_excel('datos_combinados_produccioncarbonifera.xlsx', index=False)

    

Figura 6. Exportación de la data combinada.

 

SEGUNDA PARTE: ANÁLISIS Y VISUALIZACIÓN DE LOS DATOS

El notebook desarrollado lo puedes encontrar en: Notebook

Ahora usaremos la data de producción metálica generada en la parte 1, se describen pasos a paso del procesamiento previo de la data, como tratamiento de valores nulos, modificación de valores y estandarización de datos, luego se abordará la visualización mediante diferentes tipos de gráficos.

Antes de poder realizar visualizaciones es importante conocer nuestros datos, en este caso trabajamos con el archivo data_prod_metalica.csv, la cual tiene las siguientes características:

  • 13 variables “float64”, 10 variables tipo “object”, 1 variable tipo “int64”
  • 24 columnas y 3504 filas
  • Nombre de columnas tipo categóricas: MINERAL, UNIDAD DE MEDIDA, ETAPA, PROCESO, ESTRATO, TITULAR, UNIDAD, DEPARTAMENTO, PROVINCIA, DISTRITO
  • Nombre de columnas tipo numéricas: ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC, VALOR ACUMULADO, AÑO
  • 5237 valores nulos en toda la data (83 en variables categóricas y 5154 en variables numéricas).

En la variable PROCESO se tiene 83 valores nulos el cual tiene los siguientes valores únicos “FLOTACIÓN”, “GRAVIMETRÍA”, “LIXIVIACIÓN” y “nan”. En este caso se puede optar por eliminar estos valores nulos ya que representan aproximadamente el 2.4% de la data total, también se puede reemplazar por un proceso “DESCONOCIDO”, para no perder la data que se puede usar en otro tipo de análisis que no necesite la información de esta variable.

 

Python

Copy code



data_prod_metalica["PROCESO"] = data_prod_metalica["PROCESO"].fillna("DESCONOCIDO")
data_prod_metalica.isnull().sum()

    

El resto de datos faltantes corresponde a las columnas de los meses, se debe entender que los datos correspondientes al año 2024 sólo toma en cuenta los meses de enero y febrero, por lo que los datos faltantes puede corresponder a la no lectura de los meses posteriores. En este caso se opta por asignar el valor de 0.

 

Python

Copy code



data_prod_metalica = data_prod_metalica.fillna(0)
data_prod_metalica.isnull().sum()

    

 Ahora se revisan los valores únicos en algunas variables categóricas.

Python

Copy code



nombre_columna = ["MINERAL", "UNIDAD DE MEDIDA", "ETAPA", "PROCESO", "ESTRATO", "DEPARTAMENTO"]
valores_unicos = {}
for columna in nombre_columna:
    valores_unicos[columna] = data_prod_metalica[columna].unique()


print(f"Los valores_unicos de la variable {columna} son {valores_unicos}")

    

En el caso de la variable MINERAL el nombre “ESTAÑO” se repite pero con un espacio en blanco “ESTAÑO “, también en la variable “UNIDAD DE MEDIDA” se tiene varios nombres diferentes que en unos casos representan lo mismo “TMF”, “g FINOS”, “kg FINOS”, “GR. FINOS”, “KG FINOS”, “G. FINOS”, también en la variable DEPARTAMENTO se tiene lo siguiente “JUNIN”, “JUNÍN”, “APURIMAC” y “APURÍMAC”, primero solucionamos estas coincidencias.

 

Python

Copy code



data_prod_metalica["MINERAL"] = data_prod_metalica["MINERAL"].replace({"ESTAÑO ": "ESTAÑO"})
data_prod_metalica["MINERAL"].value_counts()


data_prod_metalica["DEPARTAMENTO"] = data_prod_metalica["DEPARTAMENTO"].replace({"JUNIN": "JUNÍN", "APURIMAC": "APURÍMAC"})
data_prod_metalica["DEPARTAMENTO"].value_counts()


data_prod_metalica["UNIDAD DE MEDIDA"] = data_prod_metalica["UNIDAD DE MEDIDA"].replace({"g FINOS":"GMF", "GR. FINOS":"GMF", "G. FINOS":"GMF", "kg FINOS":"KMF", "KG. FINOS":"KMF"})
data_prod_metalica["UNIDAD DE MEDIDA"].value_counts()

    

La variable UNIDAD DE MEDIDA se puede optar por trabajar por cada unidad por separado o en este caso pasar todas las medidas a la misma unidad, pasar todo a TMF también se debe realizar la transformación a los datos que se tiene en las variables de los meses y en VALOR ACUMULADO, para no tener un análisis erróneo. 

 

Python

Copy code



# Función para convertir gramos a toneladas
def gr_a_ton(valor):
    return valor / 1_000_000

# Función para convertir kilogramos a toneladas
def kg_a_ton(valor):
    return valor / 1_000

# Verificar la unidad de medida y aplicar conversiones
for indice, fila in data_prod_metalica.iterrows():
    if fila['UNIDAD DE MEDIDA'] == 'GMF':
        for columna in col[10:23]:
            data_prod_metalica.at[indice, columna] = gr_a_ton(fila[columna])
    elif fila['UNIDAD DE MEDIDA'] == 'KMF':
        for columna in col[10:23]:
            data_prod_metalica.at[indice, columna] = kg_a_ton(fila[columna])

# Actualizar la unidad de medida
data_prod_metalica['UNIDAD DE MEDIDA'] = 'TMF'

    

Al tener varios minerales podemos dividir el DataFrame en varios DataFrame considerando un grupo de minerales, esto puede ayudar a tener una mejor visualización de las gráficas que se realizarán posteriormente.

  • data_prod_metalica_1 con los siguientes minerales “HIERRO”, “COBRE”, “ZINC”, “PLOMO”, “ESTAÑO”.
  • data_prod_metalica_2 con los siguientes minerales “ARSÉNICO”, “MANGANESO”, “MOLIBDENO”, “PLATA”.
  • data_prod_metalica_3 con los siguientes minerales “BISMUTO”, “CADMIO”, “MAGNESIO”, “ORO”, “SELENIO”.

 

Python

Copy code



data_1= data_div["MINERAL"].isin(["HIERRO", "COBRE", "ZINC", "PLOMO", "ESTAÑO"])
data_prod_metalica_1 = data_div[data_1].reset_index(drop=True)


data_2 = data_div["MINERAL"].isin(["ARSÉNICO", "MANGANESO", "MOLIBDENO", "PLATA"])
data_prod_metalica_2 = data_div[data_2].reset_index(drop=True)


data_3 = data_div["MINERAL"].isin(["BISMUTO", "CADMIO", "MAGNESIO", "ORO", "SELENIO"])
data_prod_metalica_3 = data_div[data_3].reset_index(drop=True)

    

Para los siguientes apartados se usa la función PIVOT y la operación GROUPBY para generar graficos. Con "pivot" se puede reorganizar una tabla de datos, cambiando el formato de la tabla, muy util para analizar datos en una tabla con varias columnas y filas. Permite especificar como organizar las filas y columnas de los datos.

Mientras que "groupby" en Pandas se usa para dividir los datos en grupos basados en algún criterio y luego aplicar una función (sumar, contar, promediar, etc.) a cada grupo por separado.

Con la data ya tratada, nos podemos realizar algunas preguntas como:

 

¿CUÁL ES EL TOTAL DE PRODUCCIÓN POR MINERAL METÁLICO EN EL PERÚ EN EL PERIODO 2020 - 2024?

 

Python

Copy code



def grafico_metalico_total(data):
    
    colors = ["#F9E4D4", "#D67D3E", "#9C0F48", "#470D21", "#B80000"]

    plt.figure(figsize=(6, 4))

    ax = data.plot(kind='barh', color=colors)

    # Crear leyenda personalizada
    legend_labels = [(c, '{:,.2f} TMF'.format(data[c])) for c in data.index]
    handles = [plt.Rectangle((0,0),1,1, color=colors[i], label=label) for i, label in enumerate(legend_labels)]
    plt.legend(handles=handles, loc='upper right')

    plt.grid(axis='x')
    plt.title('TOTAL DE PRODUCCION POR MINERAL METALICO', fontsize=18)
    plt.ylabel('MINERAL')
    plt.xlabel('VALOR ACUMULADO')
    ######
    plt.savefig("FIGURA7.jpg", bbox_inches='tight')
    ######
    plt.show()

    

Figura 7. Producción por mineral metálico (primer grupo de minerales).

 

Figura 8. Producción por mineral metálico (segundo grupo de minerales).

 

Figura 9. Producción por mineral metálico (tercer grupo de minerales).

 

Siendo el HIERRO el mineral con mayor cantidad de producción total (50 371 114.84 TMF) en el periodo 2020 - 2024.

 

¿CUÁL ES LA PRODUCCIÓN DE MINERAL METÁLICO POR AÑO EN EL PERÚ?

 

Python

Copy code



def grafico_metalico_por_año(data):
    # Definir los colores para cada año
    colores_por_año = {'2020': "#F9E4D4", '2021': "#9C0F48", '2022': "#D67D3E", '2023': "#470D21", '2024': "#B80000"}

    plt.figure(figsize=(8, 4))

    # Iterar sobre los grupos de años y minerales
    for (año, mineral), valor in data.items():
        # Obtener el color correspondiente al año
        color = colores_por_año[str(año)]

        # Graficar la barra
        plt.bar(f'{año} / {mineral}', valor, color=color)

    plt.grid(axis='x')
    plt.title('TOTAL DE PRODUCCION DE MINERAL METALICO POR AÑO', fontsize=18, pad=20)
    plt.ylabel('VALOR ACUMULADO POR AÑO (TMF)')
    plt.xlabel('AÑO / MINERAL')
    plt.xticks(rotation=90)  # Rotar etiquetas del eje x para mejor legibilidad
    plt.tight_layout()  # Ajustar el diseño para evitar que las etiquetas se solapen

    ######
    plt.savefig("FIGURA.jpg", bbox_inches='tight')
    ######
   
    plt.show()

    

Figura 10. Producción de mineral metálico por año (primer grupo de minerales).

 

Figura 11. Producción de mineral metálico por año (segundo grupo de minerales).

 

Figura 12. Producción de mineral metálico por año (tercer grupo de minerales).

 

El HIERRO es el mineral con mayor cantidad de producción durante todos los años (2020 - 2024) además se observa un incremento en la producción anual en cada año. Tam,bién en el caso del COBRE, aunque su producción se observa por debajo del HIERRO, muestra ligeros incrementos a cada año.

 

¿CUÁL ES LA PRODUCCIÓN TOTAL ANUAL DE MINERALES METÁLICOS POR DEPARTAMENTO?

 

Python

Copy code



def grafico_metalico_por_departamento(data):

    pivot_met1 = pd.pivot_table(
        data,
        index = "AÑO",
        values = "VALOR ACUMULADO",
        columns = "DEPARTAMENTO",
        aggfunc = "sum"
    )
    pivot_met1 = pivot_met1.fillna(0)

    minerales_unicos = data['MINERAL'].unique()
    # Concatenar los nombres de los minerales
    nombres_minerales = " ".join(minerales_unicos)

    plt.figure(figsize=(10, 10))

    pivot_met1.plot(kind='bar', width=0.8)

    plt.grid(axis='x')
    plt.title('TOTAL DE PRODUCCION POR DEPARTAMENTO', fontsize=18, pad=20)
    plt.ylabel('VALOR ACUMULADO')
    plt.xlabel('AÑO')
    plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

    plt.yscale('log')
    #plt.tight_layout(pad=1.0)
    plt.subplots_adjust(left=0.1, bottom=0.1, right=0.9, top=0.9)
    plt.figtext(0.5, -0.1, f"Minerales: {nombres_minerales}", fontsize=10, ha='left')

    ######
    plt.savefig("FIGURA.jpg", bbox_inches='tight')
    ######
   
    plt.show()

    

Descripción de la imagen

Figura 13. Producción total por departamento (primer grupo de minerales).

 

Descripción de la imagen

Figura 14. Producción total por departamento (segundo grupo de minerales).

 

Figura 15. Producción total por departamento (tercer grupo de minerales).

 

Del primer grupo de minerales  (cobre, estaño, hierro, plomo y zinc) el departamento con mayor producción en todos los años fue ICA. Para el segundo grupo de minerales (arsénico, manganeso, molibdeno y plata) el departamento que reporto mayor producción fue Ayacucho, y en el tercer grupo de minerales (bismuto, cadmio, magnesio, oro y selenio) fue LIMA quien se mantuvo como el mayor productor de estos minerales.

 

¿CUÁL ES LA PRODUCCIÓN TOTAL DE MINERAL METÁLICO POR CADA DEPARTAMENTO EN CADA AÑO?

 

La siguiente función crea una tabla "pivot" que muestra la producción total anual de mineral por departamento, con "pivot_table" se agrupa  y suma los valores acumulados por año y por departamento.

Tambien se crea otra tabla "pivot" que muestra la producción de cada mineral por año para un departamento en específico, se filtra los datos para el departamento especificado y con "pivot_table" se agrupa y suma los valores acumulados. La figura generada tiene varios subplots, la primera columna muestra un grafico de barras y lineas que muestra la producción total de minerales para un departamento en específico, mientras que la segunda columna se muestran 5 subplots en la que se muestra los minerales que produce en total por año dicho departamento, se debe considerar que la data que se llama contiene cierto grupo de minerales.

Este gráfico detalla mejor la producción mineral de un departamento segun el año. A continuación de muestra un par de ejemplos.

 

Python

Copy code



def AnalisisProductosMetalicosPorDepartamento(data, departamento):

    # Produccion total anual de producto por departamento
    pivot = pd.pivot_table(
        data,
        index = "AÑO",
        values = "VALOR ACUMULADO",
        columns = "DEPARTAMENTO",
        aggfunc = "sum"
     ).fillna(0)

    # Produccion por mineral por cada departamento
    pivot1 = pd.pivot_table(
        data[data["DEPARTAMENTO"] == departamento],
        index = "AÑO",
        values = "VALOR ACUMULADO",
        columns = "MINERAL",
        aggfunc = "sum"
    ).fillna(0)

    columna = pivot1.columns.tolist()
    indice1 = pivot1.index.tolist()
    limx_sup = pivot1.max().max()
    indice = pivot.index.tolist()

    figure=plt.figure(figsize=(10, 10), tight_layout=True)

    for i, columna in enumerate(columna):

        valores = [round(valor,2) for valor in pivot1[columna].tolist()]

        axs = figure.add_subplot(5,2,i*2+2,
                                title=f'TOTAL PRODUCCION DE {columna}',
                                xlabel="AÑO",
                                xlim=(2019,2025)
                                )

        axs.plot(pivot1.index, pivot1[columna], marker='o', color="#D8AE7E")
        axs.grid(axis='both')

        for j, valor in enumerate(valores):
            valor_texto = f'{valor / 1_000:.2f}k'
            if indice1[j] > 2023:
                va = "bottom"
            else:
                va = "top"
            axs.text(indice1[j], valor, valor_texto, ha="left", va=va)

    axes1 = figure.add_subplot(1,2,1,
                              title=f'TOTAL DE PRODUCCION ANUAL EN {departamento}',
                              xlabel="AÑO",
                              ylabel="VALOR ACUMULADO")

    axes1.plot(pivot.index, pivot[departamento], linestyle='--', marker='o', color="#481E14")
    axes1.grid(axis='both')
    valores1 = [round(valor,2) for valor in pivot[departamento].tolist()]

    for i, valor in enumerate(valores1):
        valor_texto = f'{valor / 1_000:.2f}k'
        axes1.text(indice[i], valor, valor_texto, ha="center", va="bottom")

    axes2 = axes1.twinx()
    axes2.bar(pivot.index, pivot[departamento], color="#F2613F", alpha=0.5)

    axes1.set_xlim(2019, 2025)
    axes1.set_ylim(0, limx_sup + limx_sup * 0.3)
    axes2.set_ylim(0, limx_sup + limx_sup * 0.3)
    #axes2.set_yscale("log")

    ######
    plt.savefig("FIGURA.jpg", dpi=300, bbox_inches='tight')
    ######

    plt.show()

    

Figura 16. Información detallada de producción de minerales en ICA por año.

 

Figura 17. Información detallada de producción de minerales en Puno por año.

 

¿QUÉ CANTIDAD TOTAL Y TIPO DE MINERAL PRODUJO CADA DEPARTAMENTO EN EL PERIODO 2020 - 2024?

 

El siguiente gráfico muestra la producción total por departamento/mineral (según el grupo de minerales que se llame en la data), también muestra superpuesto un gráfico de lineas indicando los valores que alcanza cada barra.

 

Python

Copy code



def grafico_mineral_prod_por_departamento(data):

    ciudad = data.groupby(["DEPARTAMENTO", "MINERAL"])
    suma = ciudad["VALOR ACUMULADO"].sum()
    df_suma = suma.reset_index()

    indices = df_suma.index.tolist()
    colores = {'APURÍMAC': "#F9E4D4", 'AREQUIPA': "#9C0F48", 'AYACUCHO': "#D67D3E", 'CAJAMARCA': "#470D21", 'CUSCO': "#B80000",
              'HUANCAVELICA': "#F9E4D4", 'HUÁNUCO': "#9C0F48", 'ICA': "#D67D3E", 'JUNÍN': "#470D21", 'LA LIBERTAD': "#B80000",
              'LIMA': "#F9E4D4", 'MOQUEGUA': "#9C0F48", 'PASCO': "#D67D3E", 'PUNO': "#470D21", 'TACNA': "#B80000", "ÁNCASH":"#F9E4D4",
               'PIURA':'#5F8670', 'MADRE DE DIOS':'#5F8670'}

    plt.figure(figsize=(10, 6))

    for (departamento, mineral), valor in suma.items():

            color = colores[departamento]

            # Graficar la barra
            plt.bar(f'{departamento} / {mineral}', valor, color=color)

    suma.plot(kind='line', style="--", marker='o', color="green")

    plt.title('TOTAL DE PRODUCCION POR DEPARTAMENTO/MINERAL', fontsize=18, pad=40)
    plt.ylabel('VALOR ACUMULADO')
    plt.xlabel('DEPARTAMENTO/MINERAL')
    #plt.legend()
    plt.xticks(rotation=90)
    plt.ylim(0.001, 10**11)
    plt.yscale('log')

    valores1 = [round(valor,2) for valor in df_suma["VALOR ACUMULADO"]]

    for i, valor in enumerate(valores1):
        valor_texto = f"{valor / 1_000:.4f}k"
        # Calcula el desplazamiento relativo para el texto basado en la escala logarítmica
        offset = np.log10(valor) * 0.4
        plt.text(indices[i], valor * (1 + offset), valor_texto, ha="center", va="bottom", rotation=90)

    ######
    plt.savefig("FIGURA.jpg", dpi=300, bbox_inches='tight')
    ######
   
    plt.show()

    

Figura 18. Producción total por Departamento/Mineral (primer grupo de minerales).

 

Figura 19. Producción total por Departamento/Mineral (segundo grupo de minerales).

 

Figura 20. Producción total por Departamento/Mineral (tercer grupo de minerales).

 

¿CUÁL ES LA PRODUCCIÓN TOTAL POR AÑO EN CADA ESTRATO?

 

El siguiente gráfico dona muestra la producción por estrato, es decir si es RÉGIMEN GENERAL, PEQUEÑO PRODUCTOR MINERO o PRODUCTOR MINERO ARTESANAL. Se hace uso del manejo de las etiquetas para tener una mejor visualización de los valores de cada ESTRATO ya que se tenia el problema que al ser muy pequeño el sector circular los valores se superponian. Este problema se resuelve con el método "annotate", el cual coloca texto o anotaciones en una gráfica en una posición especifica (según las coordenadas que se definien en las variables "X" y "Y" que se calcúlan en relación con el ángulo del sector de la dona). La alineación se controla en relación con las coordenadas "X" y "Y", mediante los argumentos "horizontalalignment" y "verticalalignment", también se usa un desplazamiento adicional respecto a las coordenadas del centro de la dona, con "xytext".

 

Python

Copy code



def grafico_dona_produccion_por_estrato(data):

    estrato = data.groupby(["AÑO", "ESTRATO", "MINERAL"])
    df_estrato = estrato["VALOR ACUMULADO"].sum().reset_index()

    colores_estrato = {
        'RÉGIMEN GENERAL': '#0C2D57',
        'PEQUEÑO PRODUCTOR MINERO': '#FC6736',
        'PRODUCTOR MINERO ARTESANAL': '#50623A'
    }

    # subtitulos
    minerales_unicos = data['MINERAL'].unique()
    nombres_minerales = " ".join(minerales_unicos)

    # Crear la figura y los ejes
    fig, axs = plt.subplots(3, 2, figsize=(6, 8), sharex=True, gridspec_kw={'wspace': 2, 'hspace': 1.2}, subplot_kw=dict(aspect="equal"))

    for i, año in enumerate(range(2020, 2025)):
        if i == 5:
            break

        fila = i // 2
        columna = i % 2

        df_año = df_estrato[df_estrato['AÑO'] == año]
        agrupado = df_año.groupby('ESTRATO')['VALOR ACUMULADO'].sum()

        # Obtener los nombres de los estratos y sus valores
        nombres_estrato = agrupado.index.tolist()
        valores_estrato = agrupado.values.tolist()

        # Obtener los colores de acuerdo al diccionario
        colores = [colores_estrato[estrato] for estrato in nombres_estrato]

        # Figura subplots
        wedges, texts = axs[fila, columna].pie(valores_estrato, wedgeprops=dict(width=0.5), startangle=-40, colors=colores)

        bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
        kw = dict(arrowprops=dict(arrowstyle="-"),
                  bbox=bbox_props, zorder=0, va="center")

        for i, p in enumerate(wedges):
            ang = (p.theta2 - p.theta1)/2. + p.theta1
            y = np.sin(np.deg2rad(ang))
            x = np.cos(np.deg2rad(ang))
            horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
            connectionstyle = f"angle,angleA=0,angleB={ang}"
            kw["arrowprops"].update({"connectionstyle": connectionstyle, "color":colores[i]})
            label = f'{nombres_estrato[i]}:\n {valores_estrato[i]:.4f} TMF'

            radius = 2.7 if valores_estrato[i] < 10 else 1.2
            axs[fila, columna].annotate(label, xy=(x, y), xytext=(1.35*np.sign(x), radius*y),
                        horizontalalignment=horizontalalignment, **kw, fontsize=8)
            axs[fila, columna].set_title(f"PRODUCCION POR\nESTRATO EN {año}", pad=20)
    axs[2, 1].axis('off')
    plt.figtext(0.5, 0.01, f"Minerales: {nombres_minerales}", fontsize=10, ha='left')

    ######
    plt.savefig("FIGURA.jpg", dpi=300, bbox_inches='tight')
    ######
   
    plt.show()

    

Aquí una muestra:

 

Figura 21. Producción por estrato por cada año.

 

¿CUÁL ES RANKING DE EMPRESAS EN PRODUCIR CIERTO MINERAL?

 

Para responder esta pregunta primero se debe realizar un tratamiento previo que no se vio anteriormente, de la columna TITULAR obtenemos los valores únicos, luego se elimina las tildes y otros símbolos para eliminar valores duplicados que están considerando las tildes.

 

Python

Copy code



ranking["TITULAR ST"] = ranking['TITULAR'].str.normalize('NFKD').str.encode('ascii', errors='ignore').str.decode('utf-8')
ranking["TITULAR ST"].unique()

    

 La siguiente función nos genera un ranking de las 10 empresas que más producen cierto mineral, el ranking lo realiza según el año y mineral correspondiente.

 

Python

Copy code



def top_prod_titular(año, mineral):

    ranking_anual = ranking[ranking["AÑO"] == año]
    ranking_anual_mineral = ranking_anual[ranking_anual["MINERAL"] == mineral]
    top_empresa = ranking_anual_mineral.groupby("TITULAR ST")["VALOR ACUMULADO"].sum()

    top_empresa = top_empresa.reset_index()
    top_empresa["VALOR ACUMULADO"].max()

    top10 = top_empresa.nlargest(10, "VALOR ACUMULADO", keep='all')

    top10_format = top10.copy()
    top10_format["VALOR ACUMULADO"] = top10_format["VALOR ACUMULADO"].apply(lambda x: '{:,.2f} TMF'.format(x))

    limx_sup = top10["VALOR ACUMULADO"].max()

    plt.figure(figsize=(6, 4))

    # Graficar las barras horizontales
    plt.barh(top10['TITULAR ST'], top10['VALOR ACUMULADO'], color='#9C0F48')

    # Añadir etiquetas de texto a cada barra
    for index, value in enumerate(top10['VALOR ACUMULADO']):
        plt.text(value, index, f'{value / 1_000:.4f}k'.format(value))  # Formatear el valor con comas y dos decimales

    plt.xlabel('VALOR ACUMULADO')
    plt.ylabel('TITULAR')

    plt.xlim(0.01, limx_sup + limx_sup * 0.3)

    plt.title(f'TOP 10 TITULARES EN PRODUCIR {mineral} EN {año}')

    ######
    plt.savefig("FIGURA.jpg", dpi=300, bbox_inches='tight')
    ######

    plt.show()

    return top10_format

    

Figura 22. Top 10 titulares en producir cobre en 2022.

 

Figura 23. Top 10 titulares en producir oro en 2023.

 

VISUALIZACIÓN DE DATOS EN MAPAS GEOGRÁFICOS

 

¿CUÁL ES LA PRODUCCIÓN DE MINERAL TOTAL POR DEPARTAMENTO?

 

En este caso se está usando data geográfica (geojson) para obtener el mapa departamental del Perú y poder graficar sobre ella con mapbox. Al revisar el geojson se observa que no utiliza tildes en el nombre de los departamentos, lo cual difiere de nuestros datos. Esto debe ser ajustado. También nuestros datos no tienen los nombres de todos los departamentos del Perú, esto puede originar un error al asignar los valores correctos de producción a cada departamento. Para corregir esto se crea DataFrame extras que contengan esta información, en este caso como no se tomó lecturas en estos departamentos se considera un valor de producción de 0 TMF. En el caso de la variable MINERAL se coloca “NO MINERAL” como valor.

 

Python

Copy code



def mod_DataFrameA(data):

    a = data.groupby("DEPARTAMENTO ST")["VALOR ACUMULADO"].sum().reset_index()

    fila = [{"DEPARTAMENTO ST":"AMAZONAS", "VALOR ACUMULADO":0},
            {"DEPARTAMENTO ST":"CALLAO", "VALOR ACUMULADO":0},
            {"DEPARTAMENTO ST":"LAMBAYEQUE", "VALOR ACUMULADO":0},
            {"DEPARTAMENTO ST":"LORETO", "VALOR ACUMULADO":0},
            {"DEPARTAMENTO ST":"SAN MARTIN", "VALOR ACUMULADO":0},
            {"DEPARTAMENTO ST":"TUMBES", "VALOR ACUMULADO":0},
            {"DEPARTAMENTO ST":"UCAYALI", "VALOR ACUMULADO":0}]
    df_fila = pd.DataFrame(fila)

    a = pd.concat([a, df_fila], ignore_index=True)
    a = a.sort_values(by="DEPARTAMENTO ST")
    df_a = a.reset_index(drop=True)

    return df_a


def mod_DataFrameB(data):

    b = data.groupby("DEPARTAMENTO ST")["MINERAL"].unique().reset_index()

    filab = [{"DEPARTAMENTO ST":"AMAZONAS", "MINERAL":"No Mineral"},
            {"DEPARTAMENTO ST":"CALLAO", "MINERAL":"No Mineral"},
            {"DEPARTAMENTO ST":"LAMBAYEQUE", "MINERAL":"No Mineral"},
            {"DEPARTAMENTO ST":"LORETO", "MINERAL":"No Mineral"},
            {"DEPARTAMENTO ST":"SAN MARTIN", "MINERAL":"No Mineral"},
            {"DEPARTAMENTO ST":"TUMBES", "MINERAL":"No Mineral"},
            {"DEPARTAMENTO ST":"UCAYALI", "MINERAL":"No Mineral"}]
    df_filab = pd.DataFrame(filab)

    b = pd.concat([b, df_filab], ignore_index=True)
    b = b.sort_values(by="DEPARTAMENTO ST")
    df_b = b.reset_index(drop=True)

    return df_b

    

 Este ciclo for genera el gráfico para cada año.

 

Python

Copy code



for año in range(2020, 2025):

    df_año = data_mapas[data_mapas["AÑO"] == año]

    data1 = mod_DataFrameA(df_año)
    data2 = mod_DataFrameB(df_año)

    fig = px.choropleth_mapbox(data_frame=data1,
          geojson=departamentos,
          locations=data1["DEPARTAMENTO ST"],
          featureidkey="properties.NOMBDEP",
          color=data1["VALOR ACUMULADO"],
          color_continuous_scale="reds",
          hover_name=data2["MINERAL"],
          width=650,height=850,
          center={"lat":-9.1900, "lon":-75.0152},
          mapbox_style="carto-positron",
          zoom=4.5)
    fig.update_layout(title_text = f"PRODUCCION DE MATERIAL METALICO TOTAL DEL AÑO {año}")

    fig.show()

    

Figura 24. Mapa geográfico de producción total en 2023.

 

CONCLUSIONES

 

Estos son solo algunos ejemplos de análisis y visualizaciones que se pueden realizar sobre nuestra data haciendo uso de herramientas de Python. Conocer la naturaleza de nuestros datos, así como los pasos de tratamiento de archivos, manipulación de los datos, limpieza, agregar contenido, creación de nuevas variables, por citar unos ejemplos, nos ayudan a preparar, garantizar la calidad y comprender eficazmente los datos para un correcto análisis, y con esto tomar las decisiones correctas. 

 

REFERENCIAS

 

Comentarios

Registrate o Inicia Sesión para comentar y obtener Cursos de pago gratis

function loadurl(){ var val1 = document.getElementById("valor3").value; console.log(val1); if(val1){ window.location = "/comunidad/blog/filtrar/"+val1+"/"} }