Análisis descriptivo de la Línea 144
Este proyecto surge con el objetivo de poner a prueba mis habilidades en programación, estadística descriptiva y visualización de los datos.
El código fue escrito en Python y como entorno de desarrollo elegí utilizar Jupyter Lab controlado desde la terminal de Git.
Para la manipulación de los datos utilicé las librerias de Pandas y Numpy, en tanto para la visualización y creación de los gráficos que se muestran en este análisis utilicé Matplotlib y Seaborn
El repositorio con el código lo puedes encontrar haciendo click aquí. Además, te dejaré la versión pdf de mi análisis que lo podrás descargar y el código que escribí.
A continuación, el código:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#Almacenamos nuestros tablas en variables con la función rad_csv de Pandas.
df_2020 = pd.read_csv("../Dataframes/linea144-2020.csv")
df_2021 = pd.read_csv("../Dataframes/linea144-2021.csv")
df_2022 = pd.read_csv("../Dataframes/linea144-2022.csv")
df_2023 = pd.read_csv("../Dataframes/linea144-2023.csv")
#En esta celda iremos manipulando nuestras dataframes para que al momento de concatenar los 4 archivos no tengamos ninguna complicación.
df_2022.pop(df_2022.columns[-1])
df_2022 = df_2022.rename(columns={
'Fecha': 'fecha'
})
df_2023 = df_2023.rename(columns={
'Fecha': 'fecha'
})
dataframes = [df_2020, df_2021, df_2022, df_2023]
df = pd.concat(dataframes, ignore_index=True)
#Eliminamos los filas duplicadas y tratamos los valores nulos.
df = df.drop_duplicates()
df = df.fillna('Missing')
#Hechamos un primer vistazo a nuestro dataframe con la función head()
df.head()
#Creamos un dataframe que contengan la cantidad de llamados según la edad del denunciante.
df_edades = df['edad_persona_en_situacion_de_violencia'].value_counts()
df_edades = pd.DataFrame({'Edad': df_edades.index, 'Cantidad de llamadas': df_edades.values})
df_edades = df_edades[df_edades['Edad'] != 'Missing']
df_edades = df_edades.sort_values(by='Edad', ascending=True)
df_edades
#Calculamos la edad media de los llamantes.
edad_media_llamantes = round(df_edades['Edad'].mean(), 0)
edad_media_llamantes
#Graficamos la distribución de la edad de los llamantes.
plt.figure(figsize=(6,6), dpi=120)
sns.lineplot(data=df_edades,
x='Edad', y='Cantidad de llamadas',
linewidth=2,
color='#e0b1cb')
ax = plt.gca()
ax.spines['bottom'].set_color('#9f86c0')
ax.spines['bottom'].set_linewidth(1.5)
ax.spines['left'].set_color('#9f86c0')
ax.spines['left'].set_linewidth(1.5)
ax.tick_params(axis='x', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
ax.tick_params(axis='y', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
ax.set_ylabel('Cantidad de llamados', color='#9f86c0', labelpad=15, size=11)
ax.set_xlabel('Rango de edades (en años)', color='#9f86c0', labelpad=15, size=11)
text_info = f'Edad media de los llamantes: {edad_media_llamantes: .0f} años'
plt.text(0.45, 0.5,
text_info,
transform=ax.transAxes,
color='white', fontsize=11,
bbox=dict(facecolor='#e0b1cb', edgecolor='#e0b1cb', pad=6))
sns.despine(trim=True)
plt.show();
#Generamos una tabla con todos los géneros declarados y la cantidad total de llamados por cada uno de ellos.
df['genero_persona_en_situacion_de_violencia'] = df['genero_persona_en_situacion_de_violencia'].replace({
'Transgénero': 'Transgenero',
'Varón Trans': 'Varon trans',
'Varon Trans': 'Varon trans'
})
generos = df['genero_persona_en_situacion_de_violencia'].value_counts()
generos = pd.DataFrame({'Género': generos.index, 'Conteo': generos.values})
generos = generos[generos['Género'] != 'Missing']
generos
#En estas líneas de código, excluimos el género MUJER con el objetivo de graficar los demás géneros.
generos_otros = generos[generos['Género'] != 'Mujer']
generos_otros;
#Por último, agrupamos todos los géneros que sean distintos al de la categoría mujer con el objetivo de comparar proporciones númericas entre ambas variables.
generos.loc[~generos['Género'].isin(['Mujer']), 'Género'] = 'Otros'
generos_mujer_y_otros = generos.groupby('Género', as_index=False).sum()
generos_mujer_y_otros;
fig, ax = plt.subplots(figsize = (6,6),
dpi = 120)
palette = ['#E0B1CB', '#BE95C4', '#9F86C0', '#5E548E', '#231942']
ax.pie(generos_mujer_y_otros['Conteo'],
colors = palette[0:4:3],
frame = True)
ax = plt.gca()
ax.spines['bottom'].set_color('#9f86c0')
ax.spines['bottom'].set_linewidth(1.5)
ax.spines['left'].set_color('#9f86c0')
ax.spines['left'].set_linewidth(1.5)
ax.tick_params(axis='x', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
ax.tick_params(axis='y', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
sns.despine(trim=True)
arrow_props = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0.3', color = '#5E548E')
plt.annotate('Otros géneros',
xy = (0.8, -0.01), xytext = (1, 0.5),
fontsize = 9,
color = '#5E548E',
fontweight = 'normal',
arrowprops = arrow_props,
alpha = 0.7)
plt.annotate('¿Qué representa\n el color rosa?',
xy = (-0.48, 0.2),
fontsize = 16,
color = '#5E548E',
fontweight = 'bold',
alpha = 0.7)
plt.annotate(' Las 81.204 mujeres\nque denunciaron algún tipo \n de violencia de género.',
xy = (-0.5, -0.5),
fontsize = 12,
color = '#5E548E',
fontweight = 'normal',
alpha = 0.7)
plt.show()
fig, ax = plt.subplots(figsize = (6,6), dpi = 120)
palette2 = ['#7bdff2', '#b2f7ef', '#eff7f6', '#f7d6e0', '#f2b5d4', '#b8bedd', '#f0e6ef', '#efc3e6', '#f0a6ca', '#9c89b8', '#fde2e4', '#fad2e1', '#bcd4e6']
explode = [0.1, 0, 0, 0, 0, 0, 0, 0, 0]
ax.pie(generos_otros['Conteo'],
colors = palette2,
frame = True,
explode = explode)
ax = plt.gca()
ax.spines['bottom'].set_color('#9f86c0')
ax.spines['bottom'].set_linewidth(1.5)
ax.spines['left'].set_color('#9f86c0')
ax.spines['left'].set_linewidth(1.5)
ax.tick_params(axis='x', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
ax.tick_params(axis='y', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
legend_elements = [plt.Line2D([0], [0],
marker = 'o',
color = 'w',
label = f"{label} : {percentage:.1f}%",
markerfacecolor = color,
markersize = 12)
for label, color, percentage in zip(generos_otros['Género'], palette2, generos_otros['Conteo'] / generos_otros['Conteo'].sum() * 100)]
ax.legend(handles = legend_elements,
bbox_to_anchor = (1.05, 1),
labelspacing = 1,
loc = 'upper left',
fontsize = 10,
labelcolor = '#231942',
frameon = False)
sns.despine(trim=True)
plt.show()
df['fecha'] = pd.to_datetime(df['fecha'])
df_mes_año = df.groupby(df['fecha'].dt.to_period('M'))
df_mes_año = df_mes_año.size()
df_mes_año = pd.DataFrame({'Periodo': df_mes_año.index, 'Llamados': df_mes_año.values})
df_mes_año['Periodo'] = df_mes_año['Periodo'].dt.to_timestamp()
df_mes_año
max = df_mes_año['Llamados'].idxmax()
min = df_mes_año['Llamados'].idxmin()
plt.figure(figsize=(6,6), dpi=120)
#max = df_mes_año['Registros'].idmax()
sns.lineplot(x='Periodo', y='Llamados', data=df_mes_año,
linewidth=2,
color='#e0b1cb')
plt.xticks(rotation=45, ha='right')
ax = plt.gca()
ax.spines['bottom'].set_color('#9f86c0')
ax.spines['bottom'].set_linewidth(1.5)
ax.spines['left'].set_color('#9f86c0')
ax.spines['left'].set_linewidth(1.5)
ax.tick_params(axis='x', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
ax.tick_params(axis='y', which='both', color='#9f86c0', width=1.5, length=5, labelcolor='#9f86c0')
ax.set_ylabel('Cantidad de llamados', color='#9f86c0', labelpad=15, size=11)
ax.set_xlabel('Periodo', color='#9f86c0', labelpad=15, size=11)
#--------------------------------------------------------------------------------------------------------#
#Puntos máximos y mínimos.
plt.plot(df_mes_año['Periodo'][max], df_mes_año['Llamados'][max], 'o', markersize=5, color='#9f86c0')
plt.annotate(f'Máximo histórico',
xy=(df_mes_año['Periodo'][max], df_mes_año['Llamados'][max]),
xytext=(8, -4),
textcoords='offset points',
color='#9f86c0',
fontsize=9)
plt.plot(df_mes_año['Periodo'][min], df_mes_año['Llamados'][min], 'o', markersize=5, color='#9f86c0')
plt.annotate(f'Mínimo histórico',
xy=(df_mes_año['Periodo'][min], df_mes_año['Llamados'][min]),
xytext=(8, -4),
textcoords='offset points',
color='#9f86c0',
fontsize=9)
#--------------------------------------------------------------------------------------------------------#
sns.despine(trim=True)
plt.show()