|
import streamlit as st |
|
import pandas as pd |
|
import plotly.express as px |
|
|
|
renuevan = {'BUENOS AIRES': 35, |
|
'CATAMARCA': 2, |
|
'CHACO': 3, |
|
'CHUBUT': 3, |
|
'CIUDAD DE BUENOS AIRES': 12, |
|
'CORDOBA': 9, |
|
'CORRIENTES': 4, |
|
'ENTRE RIOS': 4, |
|
'FORMOSA': 3, |
|
'JUJUY': 3, |
|
'LA PAMPA': 2, |
|
'LA RIOJA': 3, |
|
'MENDOZA': 5, |
|
'MISIONES': 4, |
|
'NEUQUEN': 2, |
|
'RIO NEGRO': 3, |
|
'SALTA': 4, |
|
'SAN JUAN': 3, |
|
'SAN LUIS': 2, |
|
'SANTA CRUZ': 2, |
|
'SANTA FE': 10, |
|
'SANTIAGO DEL ESTERO': 4, |
|
'TIERRA DEL FUEGO': 3, |
|
'TUCUMAN': 5 |
|
} |
|
senado_2023 = ['BUENOS AIRES','FORMOSA','JUJUY','LA RIOJA','MISIONES','SAN JUAN','SAN LUIS','SANTA CRUZ'] |
|
|
|
|
|
paso = {'BUENOS AIRES': {'LLA': 1921758, 'JxC': 2537178 , 'UP':2741730, 'FIT':292039 }, |
|
'CATAMARCA': {'LLA': 29047, 'JxC': 42087 , 'UP':88614 }, |
|
'CHACO': {'LLA': 157223, 'JxC': 155806 , 'UP':204092 }, |
|
'CHUBUT': {'LLA': 114205, 'JxC': 71065 , 'UP':70919 }, |
|
'CIUDAD DE BUENOS AIRES': {'LLA': 299363, 'JxC': 796779 , 'UP':383654 }, |
|
'CORDOBA': {'LLA': 669268, 'JxC': 510671 , 'UP':161899, 'Provincial':548706 }, |
|
'CORRIENTES': {'LLA': 156173, 'JxC': 197499 , 'UP':166841 }, |
|
'ENTRE RIOS': {'LLA': 123104, 'JxC': 205869 , 'UP':226301 }, |
|
'FORMOSA': {'LLA': 72988, 'JxC': 65889 , 'UP':139031 }, |
|
'JUJUY': {'LLA': 136664, 'JxC': 94390 , 'UP':92179 }, |
|
'LA PAMPA': {'LLA': 0, 'JxC': 57816 , 'UP':53407 }, |
|
'LA RIOJA': {'LLA': 62951, 'JxC': 37858 , 'UP':57626 }, |
|
'MENDOZA': {'LLA': 438204, 'JxC': 273008 , 'UP':164284 }, |
|
'MISIONES': {'LLA': 0, 'JxC': 115551 , 'UP':143243 }, |
|
'NEUQUEN': {'LLA': 128837, 'JxC': 81859 , 'UP':62008 }, |
|
'RIO NEGRO': {'LLA': 0, 'JxC': 75224 , 'UP':87433, 'Provincial':131699 }, |
|
'SALTA': {'LLA': 290647, 'JxC': 105864 , 'UP':143746 }, |
|
'SAN JUAN': {'LLA': 125947, 'JxC': 118423 , 'UP':127218 }, |
|
'SAN LUIS': {'LLA': 119656, 'JxC': 66142 , 'UP':46949 }, |
|
'SANTA CRUZ': {'LLA': 0, 'JxC': 21594 , 'UP':31494, 'Provincial':8188 }, |
|
'SANTA FE': {'LLA': 623875, 'JxC': 555573 , 'UP':360754, 'Provincial': 61129 }, |
|
'SANTIAGO DEL ESTERO': {'LLA': 116052, 'JxC': 23209 , 'UP':254825, 'Provincial':22613 }, |
|
'TIERRA DEL FUEGO': {'LLA': 29803, 'JxC': 17937 , 'UP':21386, 'Provincial':8521 }, |
|
'TUCUMAN': {'LLA': 252489, 'JxC': 212800 , 'UP':295149 } |
|
} |
|
|
|
def dhont(results, bancas): |
|
listas, votos = list(results.keys()), list(results.values()) |
|
df = pd.DataFrame([[val/i for i in range(1, bancas+1)] for val in votos], index=listas) |
|
df = df.reset_index().rename(columns={"index": "lista"}) |
|
r = df.melt(id_vars=["lista"]).sort_values('value', ascending=False).head(bancas) |
|
return r.groupby('lista').size().to_dict() |
|
|
|
def dhont_senado(results): |
|
df = pd.DataFrame([results], index=['votos']).T |
|
partidos = list(df.sort_values('votos', ascending=False).head(2).index) |
|
return {partidos[0]:2, partidos[1]:1} |
|
|
|
def calcular_resultados(paso, renuevan, ausentes, migracion, ausentes_porcentaje): |
|
migracion_porcentajes = { |
|
lista: {destino: voto/sum(votos.values()) for destino, voto in votos.items()} |
|
for lista, votos in migracion.items() |
|
} |
|
|
|
r = [] |
|
flow = {} |
|
total = {} |
|
r_senado = [] |
|
for pcia in list(paso.keys()): |
|
results, bancas = paso[pcia], renuevan[pcia] |
|
coef_ausentes = [x/sum(ausentes.values()) for x in ausentes.values()] |
|
flow['JxC'] = results['JxC'] * (migracion_porcentajes['JxC']['JxC'] - 1) |
|
flow['JxC'] += results['LLA'] * migracion_porcentajes['LLA']['JxC'] |
|
flow['JxC'] += results['UP'] * migracion_porcentajes['UP']['JxC'] |
|
|
|
flow['LLA'] = results['LLA'] * (migracion_porcentajes['LLA']['LLA'] - 1) |
|
flow['LLA'] += results['JxC'] * migracion_porcentajes['JxC']['LLA'] |
|
flow['LLA'] += results['UP'] * migracion_porcentajes['UP']['LLA'] |
|
|
|
flow['UP'] = results['UP'] * (migracion_porcentajes['UP']['UP'] - 1) |
|
flow['UP'] += results['JxC'] * migracion_porcentajes['JxC']['UP'] |
|
flow['UP'] += results['LLA'] * migracion_porcentajes['LLA']['UP'] |
|
|
|
for i, partido in enumerate(ausentes.keys()): |
|
results[partido] = results[partido] + sum(results.values()) * ausentes_porcentaje * coef_ausentes[i] |
|
results[partido] = results[partido] + flow[partido] |
|
|
|
total[pcia] = results |
|
if pcia in senado_2023: |
|
r_senado.append(dhont_senado(results)) |
|
r.append(dhont(results, bancas)) |
|
|
|
return r, total, r_senado |
|
|
|
|
|
|
|
st.sidebar.title("Simulacion Ausentes") |
|
|
|
ausentes_porcentaje = 0.12 |
|
boundary_lla_jxc, boundary_jxc_up = st.sidebar.slider("Votos de ausentes en Paso en genrales (LLA/JxC/UP)", 0, 100, (33, 67)) |
|
|
|
ausentes_lla = boundary_lla_jxc |
|
ausentes_jxc = boundary_jxc_up - boundary_lla_jxc |
|
ausentes_up = 100 - boundary_jxc_up |
|
|
|
st.sidebar.text(f"% Ausentes por LLA: {ausentes_lla}%") |
|
st.sidebar.text(f"% Ausentes por JxC: {ausentes_jxc}%") |
|
st.sidebar.text(f"% Ausentes por UP: {ausentes_up}%") |
|
st.sidebar.markdown("\n\n", unsafe_allow_html=True) |
|
|
|
ausentes = { |
|
'LLA': ausentes_lla, |
|
'JxC': ausentes_jxc, |
|
'UP': ausentes_up |
|
} |
|
|
|
st.sidebar.title("Simulacion cambio de votos") |
|
|
|
migracion = { |
|
'JxC': { |
|
'LLA': st.sidebar.slider("% Votos JxC PASO => a LLA General", 0, 50, 0), |
|
'UP': st.sidebar.slider("% Votos JxC PASO => a UP General", 0, 50, 0), |
|
}, |
|
'LLA': { |
|
'JxC': st.sidebar.slider("% Votos LLA PASO => a JxC General", 0, 50, 0), |
|
'UP': st.sidebar.slider("% Votos LLA PASO => a UP General", 0, 50, 0), |
|
}, |
|
'UP': { |
|
'LLA': st.sidebar.slider("% Votos UP PASO => a LLA General", 0, 50, 0), |
|
'JxC': st.sidebar.slider("% Votos UP PASO => a JxC General", 0, 50, 0), |
|
} |
|
} |
|
|
|
for partido in ['JxC', 'LLA', 'UP']: |
|
migracion[partido][partido] = 100 - sum([migracion[partido][otro_partido] for otro_partido in ['JxC', 'LLA', 'UP'] if otro_partido != partido]) |
|
|
|
r, total, r_senado = calcular_resultados(paso, renuevan, ausentes, migracion, ausentes_porcentaje=0.1) |
|
|
|
st.subheader("Diputados por fuerza política") |
|
df_bancas = pd.DataFrame(data=r, index=paso.keys()).fillna(0).astype(int) |
|
df_sum = df_bancas.sum().to_frame(name='Nuevos') |
|
df_sum['Salientes'] = {'FIT':0, 'JxC':49, 'LLA':0, 'UP':76, 'Prov':5} |
|
df_sum['Netos'] = df_sum['Nuevos'] - df_sum['Salientes'] |
|
df_sum['Conserva'] = {'FIT':4, 'JxC':61, 'LLA':3, 'UP':50, 'Prov':7} |
|
df_sum['Nueva comp'] = df_sum['Conserva'] + df_sum['Nuevos'] |
|
df_sum = df_sum.loc[['JxC','LLA','UP']] |
|
|
|
df_otros = pd.DataFrame({ |
|
'Nuevos': [130 - df_sum['Nuevos'].sum()], |
|
'Salientes': [126 - df_sum['Salientes'].sum()], |
|
'Netos': [0], |
|
'Conserva': [ 126 - df_sum['Conserva'].sum()], |
|
'Nueva comp': [256 - df_sum['Nueva comp'].sum()] |
|
}, index=['Otros']) |
|
df_sum = pd.concat([df_sum, df_otros]) |
|
df_sum['Netos'] = (df_sum['Nuevos'] - df_sum['Salientes']).astype(int) |
|
|
|
st.write(df_sum) |
|
|
|
|
|
data = [] |
|
for province, seats in renuevan.items(): |
|
party_max = max(paso[province], key=paso[province].get) |
|
data.append({ |
|
'Provincia': province, |
|
'Bancas': seats, |
|
'Partido Dominante': party_max, |
|
'Votos': paso[province][party_max] |
|
}) |
|
|
|
df = pd.DataFrame(data) |
|
|
|
colors = { |
|
'LLA': '#9370DB', |
|
'JxC': '#FFD700', |
|
'UP': '#1E90FF' |
|
} |
|
|
|
|
|
df['Bancas LLA'] = df['Provincia'].apply(lambda x: df_bancas.loc[x, 'LLA'] if 'LLA' in df_bancas.columns else 0) |
|
df['Bancas JxC'] = df['Provincia'].apply(lambda x: df_bancas.loc[x, 'JxC'] if 'JxC' in df_bancas.columns else 0) |
|
df['Bancas UP'] = df['Provincia'].apply(lambda x: df_bancas.loc[x, 'UP'] if 'UP' in df_bancas.columns else 0) |
|
|
|
fig = px.treemap( |
|
df, |
|
path=['Provincia'], |
|
values='Bancas', |
|
color='Partido Dominante', |
|
color_discrete_map=colors, |
|
title="Nuevas bancas Diputados por provincia", |
|
custom_data=['Bancas LLA', 'Bancas JxC', 'Bancas UP'] |
|
) |
|
|
|
fig.update_traces( |
|
hovertemplate="<b>%{label}</b><br>Bancas Totales: %{value}<br>Bancas LLA: %{customdata[0]}<br>Bancas JxC: %{customdata[1]}<br>Bancas UP: %{customdata[2]}" |
|
) |
|
|
|
st.plotly_chart(fig) |
|
|
|
|
|
st.subheader("Diputados nuevos por provincia") |
|
st.dataframe(df_bancas, height=900, use_container_width=True) |
|
|
|
|
|
st.subheader("Senadores por Fuerza politica") |
|
df_bancas_senado = pd.DataFrame(data=r_senado, index=senado_2023).fillna(0).astype(int) |
|
df_sum_senado = df_bancas_senado.sum().to_frame(name='Nuevos') |
|
df_sum_senado['Salientes'] = {'JxC':11, 'LLA':0, 'UP':10, 'Provincial':2} |
|
df_sum_senado['Netos'] = df_sum_senado['Nuevos'] - df_sum_senado['Salientes'] |
|
df_sum_senado['Conserva'] = {'JxC':22, 'LLA':0, 'UP':23, 'Provincial':6} |
|
df_sum_senado['Nueva comp'] = df_sum_senado['Conserva'] + df_sum_senado['Nuevos'] |
|
st.write(df_sum_senado) |
|
|
|
st.subheader("Senadores Nuevos por Provincia") |
|
df_bancas_senado = pd.DataFrame(data=r_senado, index=senado_2023).fillna(0).astype(int) |
|
st.write(df_bancas_senado) |
|
|
|
st.subheader("Votos por fuerza política por provincia (Diputados)") |
|
df_votos = pd.DataFrame(data=total).T[['LLA','JxC','UP']].astype(int) |
|
st.dataframe(df_votos, height=900, use_container_width=True) |
|
|
|
|
|
|
|
|
|
import plotly.graph_objects as go |
|
st.subheader("% Votos por fuerza política total Nacional (Diputados)") |
|
st.text("Calculo de % sobre 3 fuerzas mayoritarias") |
|
p_votos = df_votos.sum() |
|
p_votos.columns = ['Porcentaje'] |
|
fig = go.Figure(data=[go.Pie(labels=p_votos.index, |
|
values=p_votos, |
|
hole=.3, |
|
textinfo='percent+label', |
|
marker=dict(colors=[colors[key] for key in p_votos.index]))]) |
|
fig.update_layout(title_text='') |
|
st.plotly_chart(fig) |
|
|