Last active
January 21, 2026 22:18
-
-
Save miguel9554/4afdde0e8030e47db3aae795c822977e to your computer and use it in GitHub Desktop.
Plot de carga fiscal del monotributo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import pandas as pd | |
| import plotly.graph_objects as go | |
| import numpy as np | |
| df = pd.DataFrame({ | |
| "Categoria": list("ABCDEFGHIJK"), | |
| "Ingreso_anual": [ | |
| 10277988.13, 15058447.71, 21113696.52, 26212853.42, | |
| 30833964.37, 38642048.36, 46211109.37, 70113407.33, | |
| 78479211.62, 89872640.30, 108357084.05, | |
| ], | |
| "Total_servicios": [ | |
| 42386.74, 48250.78, 56501.85, 72414.10, 102537.97, | |
| 129045.32, 197108.23, 447346.93, 824802.26, | |
| 999007.65, 1381687.90, | |
| ], | |
| "Total_bienes": [ | |
| 42386.74, 48250.78, 55227.06, 70661.26, 92658.35, | |
| 111198.27, 135918.34, 272063.40, 406512.05, | |
| 497059.41, 600879.51, | |
| ], | |
| }) | |
| df["Ingreso_mensual"] = df["Ingreso_anual"] / 12 | |
| # Convertir a millones | |
| df["Ingreso_anual_mill"] = df["Ingreso_anual"] / 1e6 | |
| df["Ingreso_mensual_mill"] = df["Ingreso_mensual"] / 1e6 | |
| # Redondear a 3 cifras significativas SOLO para el eje X anual | |
| df["Ingreso_anual_mill_round"] = df["Ingreso_anual_mill"].apply(lambda x: round(x, 3 - len(str(int(x))))) | |
| # Calcular mensual como anual_redondeado / 12 | |
| df["Ingreso_mensual_mill_round"] = df["Ingreso_anual_mill_round"] / 12 | |
| def crear_escalones(df, columna_total): | |
| """Crear datos para escalones (gasto constante por categoría, en millones)""" | |
| x_escalon = [] | |
| y_escalon = [] | |
| for i in range(len(df)): | |
| if i == 0: | |
| x_escalon.extend([0, df["Ingreso_anual_mill_round"].iloc[i]]) | |
| else: | |
| x_escalon.extend([df["Ingreso_anual_mill_round"].iloc[i-1], df["Ingreso_anual_mill_round"].iloc[i]]) | |
| y_mill = df[columna_total].iloc[i] / 1e6 | |
| y_escalon.extend([y_mill, y_mill]) | |
| return x_escalon, y_escalon | |
| def crear_porcentaje(df, columna_total, min_ingreso_mill=4.0): | |
| """Crear datos interpolados para porcentaje (varía continuamente)""" | |
| x_continuo = [] | |
| y_porcentaje = [] | |
| for i in range(len(df)): | |
| if i == 0: | |
| inicio = df["Ingreso_anual"].iloc[i] * 0.001 | |
| else: | |
| inicio = df["Ingreso_anual"].iloc[i-1] | |
| fin = df["Ingreso_anual"].iloc[i] | |
| n_puntos = 50 | |
| for j in range(n_puntos): | |
| ingreso = inicio + (fin - inicio) * j / (n_puntos - 1) | |
| ingreso_mill = ingreso / 1e6 | |
| if ingreso_mill >= min_ingreso_mill: | |
| x_continuo.append(ingreso_mill) | |
| porcentaje = (df[columna_total].iloc[i] * 12) / ingreso * 100 | |
| y_porcentaje.append(porcentaje) | |
| return x_continuo, y_porcentaje | |
| # Crear datos para servicios | |
| x_escalon_serv, y_escalon_serv = crear_escalones(df, "Total_servicios") | |
| x_cont_serv, y_pct_serv = crear_porcentaje(df, "Total_servicios") | |
| # Crear datos para bienes | |
| x_escalon_bien, y_escalon_bien = crear_escalones(df, "Total_bienes") | |
| x_cont_bien, y_pct_bien = crear_porcentaje(df, "Total_bienes") | |
| fig = go.Figure() | |
| color_servicios = "#1f77b4" # azul | |
| color_bienes = "#ff7f0e" # naranja | |
| # === SERVICIOS === | |
| # Escalones para gasto mensual servicios (dashed) | |
| fig.add_trace(go.Scatter( | |
| x=x_escalon_serv, | |
| y=y_escalon_serv, | |
| mode="lines", | |
| name="Servicios [ARS]", | |
| line=dict(shape='hv', color=color_servicios, dash="dash"), | |
| yaxis="y1", | |
| xaxis="x", | |
| )) | |
| # Puntos y etiquetas en los límites de categoría (servicios) | |
| fig.add_trace(go.Scatter( | |
| x=df["Ingreso_anual_mill_round"], | |
| y=df["Total_servicios"] / 1e6, | |
| mode="markers+text", | |
| text=df["Categoria"], | |
| textposition="bottom right", | |
| marker=dict(size=8, color=color_servicios), | |
| showlegend=False, | |
| yaxis="y1", | |
| xaxis="x", | |
| )) | |
| # Línea continua para porcentaje servicios (solid) | |
| fig.add_trace(go.Scatter( | |
| x=x_cont_serv, | |
| y=y_pct_serv, | |
| mode="lines", | |
| name="Servicios [%]", | |
| line=dict(color=color_servicios), | |
| yaxis="y2", | |
| xaxis="x", | |
| )) | |
| # === BIENES === | |
| # Escalones para gasto mensual bienes (dashed) | |
| fig.add_trace(go.Scatter( | |
| x=x_escalon_bien, | |
| y=y_escalon_bien, | |
| mode="lines", | |
| name="Bienes [ARS]", | |
| line=dict(shape='hv', color=color_bienes, dash="dash"), | |
| yaxis="y1", | |
| xaxis="x", | |
| )) | |
| # Puntos y etiquetas en los límites de categoría (bienes) | |
| fig.add_trace(go.Scatter( | |
| x=df["Ingreso_anual_mill_round"], | |
| y=df["Total_bienes"] / 1e6, | |
| mode="markers+text", | |
| text=df["Categoria"], | |
| textposition="bottom right", | |
| marker=dict(size=8, color=color_bienes), | |
| showlegend=False, | |
| yaxis="y1", | |
| xaxis="x", | |
| )) | |
| # Línea continua para porcentaje bienes (solid) | |
| fig.add_trace(go.Scatter( | |
| x=x_cont_bien, | |
| y=y_pct_bien, | |
| mode="lines", | |
| name="Bienes [%]", | |
| line=dict(color=color_bienes), | |
| yaxis="y2", | |
| xaxis="x", | |
| )) | |
| # Traza invisible para forzar xaxis2 | |
| fig.add_trace(go.Scatter( | |
| x=df["Ingreso_anual_mill_round"], | |
| y=[None] * len(df), | |
| xaxis="x2", | |
| yaxis="y", | |
| showlegend=False, | |
| hoverinfo="skip", | |
| )) | |
| fig.update_layout( | |
| title=f"Carga fiscal del monotributo con categorías del 1/02/2026", | |
| xaxis=dict( | |
| title="Ingreso bruto anual [millones de ARS]", | |
| tickvals=df["Ingreso_anual_mill_round"], | |
| ticktext=[f"{v:.3g}" for v in df["Ingreso_anual_mill_round"]], | |
| side="bottom", | |
| ), | |
| xaxis2=dict( | |
| title="Ingreso bruto mensual [millones de ARS]", | |
| overlaying="x", | |
| side="top", | |
| tickvals=df["Ingreso_anual_mill_round"], | |
| ticktext=[f"{v:.3g}" for v in df["Ingreso_mensual_mill_round"]], | |
| showgrid=False, | |
| ), | |
| yaxis=dict( | |
| title="Gasto mensual [millones de ARS]", | |
| range=[0, 1.7], | |
| dtick=0.25, | |
| ), | |
| yaxis2=dict( | |
| title="Gasto mensual [%]", | |
| overlaying="y", | |
| side="right", | |
| range=[0, 20.4], | |
| dtick=3, | |
| showgrid=False, | |
| ), | |
| legend=dict( | |
| x=0.01, | |
| y=0.99, | |
| xanchor="left", | |
| yanchor="top", | |
| bgcolor="rgba(255,255,255,0.8)", | |
| ), | |
| hovermode="x unified", | |
| ) | |
| fig.show() | |
| # Exportar a PNG para compartir en web (1200x800 px, escala 2x para buena resolución) | |
| fig.write_image("monotributo.png", width=1200, height=800, scale=2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment