C2MV commited on
Commit
cc01c98
·
verified ·
1 Parent(s): c463f68

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +159 -159
app.py CHANGED
@@ -3,6 +3,9 @@ import numpy as np
3
  import plotly.express as px
4
  import plotly.graph_objects as go
5
  import gradio as gr
 
 
 
6
 
7
  cities_data = {
8
  'Abancay': {
@@ -1148,6 +1151,8 @@ cities_data = {
1148
  }
1149
 
1150
 
 
 
1151
  COLORES = {
1152
  'Total': '#2C3E50',
1153
  'Hombres': '#3498DB',
@@ -1170,15 +1175,7 @@ def normalizar_nombres_ciudades(nombre):
1170
  'Juliana': 'Juliaca',
1171
  'Chimbote': 'Chimbote',
1172
  'Arequipa': 'Arequipa',
1173
- 'Trujillo': 'Trujillo',
1174
- 'Cervo de Pasco': 'Cerro de Pasco',
1175
- 'Lima Metropolitana y la Provincia Constitucional del Calleo': 'Lima-Callao',
1176
- 'Moyaegua': 'Moquegua',
1177
- 'Mayobamba': 'Moyobamba',
1178
- 'Hueva': 'Huancavelica',
1179
- 'Pluto Júnior': 'Piura',
1180
- 'Guido Mianzano': 'Cajamarca',
1181
- 'Guyo Morales': 'Ayacucho'
1182
  }
1183
  return correcciones.get(nombre, nombre)
1184
 
@@ -1198,7 +1195,10 @@ def crear_grafico_lineas(df, titulo, eje_y, formato=None):
1198
  y=df[columna],
1199
  name=columna,
1200
  mode='lines+markers',
1201
- line=dict(color=COLORES.get(columna, '#000000'), width=3),
 
 
 
1202
  marker=dict(size=8),
1203
  hovertemplate=f'<b>{columna}</b>: %{{y:{formato or ".2f"}}}<extra></extra>'
1204
  ))
@@ -1209,8 +1209,14 @@ def crear_grafico_lineas(df, titulo, eje_y, formato=None):
1209
  xaxis_title='Periodo',
1210
  hovermode='x unified',
1211
  template='plotly_white',
1212
- legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
1213
- height=400
 
 
 
 
 
 
1214
  )
1215
 
1216
  if formato:
@@ -1219,122 +1225,120 @@ def crear_grafico_lineas(df, titulo, eje_y, formato=None):
1219
  return fig
1220
 
1221
  def crear_radar_plot(dfs):
1222
- try:
1223
- metricas = {
1224
- 'Desempleo': dfs['desempleo']['Total'].iloc[-1],
1225
- 'Informalidad': dfs['informal']['Total'].iloc[-1],
1226
- 'Actividad': dfs['actividad']['Total'].iloc[-1],
1227
- 'Brecha Salarial': ((dfs['ingresos']['Hombres'].iloc[-1] -
1228
- dfs['ingresos']['Mujeres'].iloc[-1]) /
1229
- dfs['ingresos']['Hombres'].iloc[-1]) * 100
1230
- }
1231
-
1232
- fig = go.Figure()
1233
- fig.add_trace(go.Scatterpolar(
1234
- r=list(metricas.values()) + [list(metricas.values())[0]],
1235
- theta=list(metricas.keys()) + [list(metricas.keys())[0]],
1236
- fill='toself',
1237
- fillcolor='rgba(142, 68, 173, 0.2)',
1238
- line=dict(color=COLORES['Brecha'], width=2),
1239
- name='Indicadores'
1240
- ))
1241
-
1242
- fig.update_layout(
1243
- polar=dict(
1244
- radialaxis=dict(visible=True, range=[0, 100]),
1245
- angularaxis=dict(rotation=90, direction='clockwise')
1246
- ),
1247
- title=dict(text='Radar de Indicadores Clave', x=0.5, font=dict(size=22)),
1248
- showlegend=False,
1249
- height=500,
1250
- margin=dict(t=80, b=80)
1251
- )
1252
- return fig
1253
 
1254
- except Exception as e:
1255
- print(f"Error generando radar plot: {str(e)}")
 
 
 
 
 
 
 
1256
  return go.Figure()
1257
-
1258
- def crear_grafico_barras_anual(df, titulo, eje_y, columna_metricas, palette):
1259
- df['Año'] = df['Periodo'].str.split('-').str[0]
1260
- df = df.groupby(['Ciudad', 'Año'], as_index=False)[columna_metricas].mean()
1261
 
1262
- fig = px.bar(df,
1263
- x='Ciudad',
1264
- y=columna_metricas,
1265
- color='Año',
1266
- barmode='group',
1267
- title=f'<b>{titulo}</b>',
1268
- labels={columna_metricas: eje_y},
1269
- color_discrete_sequence=palette,
1270
- height=600)
 
 
 
 
1271
 
1272
  fig.update_layout(
1273
- xaxis_title='Ciudad',
1274
- yaxis_title=eje_y,
1275
- legend_title='Año',
1276
- xaxis={'categoryorder': 'total descending'},
1277
- uniformtext_minsize=8,
1278
- margin=dict(b=150, t=80),
1279
- hovermode='x unified'
1280
  )
1281
 
1282
- fig.update_xaxes(tickangle=45)
1283
  return fig
1284
 
1285
- def generar_analisis_global():
1286
- figs = []
1287
 
1288
- # 1. Ranking de Desempleo
1289
- datos_desempleo = []
1290
  for ciudad, data in cities_data.items():
1291
  nombre = normalizar_nombres_ciudades(ciudad)
1292
- df = procesar_dataframe(data['desempleo_trimestral'], ["Trimestre", "Total", "Hombres", "Mujeres"])
 
1293
  if not df.empty:
1294
- datos_desempleo.append({'Ciudad': nombre, 'Desempleo': df['Total'].iloc[-1]})
 
1295
 
1296
- if datos_desempleo:
1297
- df_desempleo = pd.DataFrame(datos_desempleo).sort_values('Desempleo', ascending=False)
1298
- fig = px.bar(df_desempleo,
1299
- x='Ciudad',
1300
- y='Desempleo',
1301
- color='Desempleo',
1302
- color_continuous_scale='Bluered',
1303
- text_auto='.1f%',
1304
- title='<b>Comparación de Tasa de Desempleo entre Ciudades</b>',
1305
- height=600)
1306
- fig.update_layout(xaxis={'categoryorder':'total descending'}, margin=dict(b=150))
1307
- figs.append(fig)
1308
- else:
1309
- figs.append(go.Figure())
1310
 
1311
- # 2. Evolución de Ingresos
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1312
  datos_ingresos = []
1313
  for ciudad, data in cities_data.items():
1314
  nombre = normalizar_nombres_ciudades(ciudad)
1315
- df = procesar_dataframe(data['ingresos_periodo'], ["Periodo", "Total", "Hombres", "Mujeres"])
 
1316
  if not df.empty:
1317
  df['Ciudad'] = nombre
1318
  datos_ingresos.append(df)
1319
 
1320
  if datos_ingresos:
1321
  df_ingresos = pd.concat(datos_ingresos)
1322
- fig_ingresos = crear_grafico_barras_anual(
1323
- df_ingresos,
1324
- 'Evolución Anual de Ingresos Promedio por Ciudad',
1325
- 'Ingresos (Soles)',
1326
- 'Total',
1327
- px.colors.sequential.Viridis
 
 
 
 
 
 
1328
  )
1329
  figs.append(fig_ingresos)
1330
  else:
1331
  figs.append(go.Figure())
1332
 
1333
- # 3. Evolución de Brecha Salarial
1334
  datos_brecha = []
1335
  for ciudad, data in cities_data.items():
1336
  nombre = normalizar_nombres_ciudades(ciudad)
1337
- df = procesar_dataframe(data['ingresos_periodo'], ["Periodo", "Total", "Hombres", "Mujeres"])
 
1338
  if not df.empty:
1339
  df['Brecha'] = (df['Hombres'] - df['Mujeres']) / df['Hombres'].replace(0, np.nan) * 100
1340
  df['Ciudad'] = nombre
@@ -1342,12 +1346,23 @@ def generar_analisis_global():
1342
 
1343
  if datos_brecha:
1344
  df_brecha = pd.concat(datos_brecha)
1345
- fig_brecha = crear_grafico_barras_anual(
1346
- df_brecha,
1347
- 'Evolución Anual de la Brecha Salarial por Ciudad',
1348
- 'Brecha Salarial (%)',
1349
- 'Brecha',
1350
- px.colors.diverging.RdYlGn
 
 
 
 
 
 
 
 
 
 
 
1351
  )
1352
  figs.append(fig_brecha)
1353
  else:
@@ -1357,7 +1372,6 @@ def generar_analisis_global():
1357
 
1358
  def actualizar_graficos(ciudad):
1359
  data = cities_data[ciudad]
1360
- nombre_ciudad = normalizar_nombres_ciudades(ciudad)
1361
 
1362
  dfs = {
1363
  'desempleo': procesar_dataframe(data['desempleo_trimestral'], ["Trimestre", "Total", "Hombres", "Mujeres"]),
@@ -1367,80 +1381,66 @@ def actualizar_graficos(ciudad):
1367
  }
1368
 
1369
  return [
1370
- crear_radar_plot(dfs),
1371
  crear_grafico_lineas(dfs['desempleo'], "Tasa de Desempleo", "%", ".1f"),
1372
  crear_grafico_lineas(dfs['ingresos'], "Ingresos Promedio", "Soles", ".0f"),
1373
  crear_grafico_lineas(dfs['informal'], "Tasa de Informalidad", "%", ".1f"),
1374
  crear_grafico_lineas(dfs['actividad'], "Tasa de Actividad", "%", ".1f"),
 
1375
  crear_grafico_lineas(dfs['ingresos'].assign(
1376
  Brecha=lambda x: (x['Hombres'] - x['Mujeres']) / x['Hombres'].replace(0, np.nan) * 100
1377
- ), "Brecha Salarial de Género", "%", ".1f")
1378
  ]
1379
 
1380
- with gr.Blocks(
1381
- title="Análisis Mercado Laboral Peruano",
1382
- css="""
1383
  .gradio-container {background-color: #f8f9fa}
1384
- .card {border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin: 10px 0; background: white}
1385
- .header {font-size: 28px; font-weight: bold; color: #2c3e50; margin-bottom: 20px}
1386
- .subheader {font-size: 20px; color: #3498db; margin: 15px 0}
1387
- """
1388
- ) as app:
1389
 
1390
- gr.Markdown("# 📊 Dashboard del Mercado Laboral Peruano", elem_classes="header")
1391
 
1392
- ciudad = gr.Dropdown(
1393
- list(cities_data.keys()),
1394
- label="Seleccionar Ciudad",
1395
- value="Chimbote",
1396
- interactive=True
1397
- )
 
1398
 
1399
  with gr.Tab("Análisis por Ciudad"):
1400
- with gr.Column(elem_classes="card"):
1401
- gr.Markdown("## 📍 Indicadores Clave", elem_classes="subheader")
1402
- radar_plot = gr.Plot()
1403
-
1404
- with gr.Column(elem_classes="card"):
1405
- gr.Markdown("## 📈 Tendencias Principales", elem_classes="subheader")
1406
- with gr.Row():
1407
- desempleo_plot = gr.Plot()
1408
- ingresos_plot = gr.Plot()
1409
- with gr.Row():
1410
- informalidad_plot = gr.Plot()
1411
- actividad_plot = gr.Plot()
1412
-
1413
- with gr.Column(elem_classes="card"):
1414
- gr.Markdown("## 📉 Brecha Salarial", elem_classes="subheader")
1415
- brecha_plot = gr.Plot()
1416
 
1417
  with gr.Tab("Análisis Comparativo"):
1418
- with gr.Column(elem_classes="card"):
1419
- gr.Markdown("## 🏙️ Comparativa entre Ciudades", elem_classes="subheader")
1420
- global_desempleo = gr.Plot()
1421
- global_ingresos = gr.Plot()
1422
- global_brecha = gr.Plot()
1423
-
1424
- @app.load()
1425
- def cargar_inicial():
1426
- datos_ciudad = actualizar_graficos("Chimbote")
1427
- datos_global = generar_analisis_global()
1428
- return {
1429
- radar_plot: datos_ciudad[0],
1430
- desempleo_plot: datos_ciudad[1],
1431
- ingresos_plot: datos_ciudad[2],
1432
- informalidad_plot: datos_ciudad[3],
1433
- actividad_plot: datos_ciudad[4],
1434
- brecha_plot: datos_ciudad[5],
1435
- global_desempleo: datos_global[0],
1436
- global_ingresos: datos_global[1],
1437
- global_brecha: datos_global[2]
1438
- }
1439
 
 
1440
  ciudad.change(
1441
  fn=actualizar_graficos,
1442
  inputs=ciudad,
1443
- outputs=[radar_plot, desempleo_plot, ingresos_plot, informalidad_plot, actividad_plot, brecha_plot]
 
 
 
 
 
 
1444
  )
1445
 
1446
- app.launch(debug=True, share=False)
 
3
  import plotly.express as px
4
  import plotly.graph_objects as go
5
  import gradio as gr
6
+ from gradio.components import Plot
7
+
8
+ #DATOS
9
 
10
  cities_data = {
11
  'Abancay': {
 
1151
  }
1152
 
1153
 
1154
+ #DATOS
1155
+
1156
  COLORES = {
1157
  'Total': '#2C3E50',
1158
  'Hombres': '#3498DB',
 
1175
  'Juliana': 'Juliaca',
1176
  'Chimbote': 'Chimbote',
1177
  'Arequipa': 'Arequipa',
1178
+ 'Trujillo': 'Trujillo'
 
 
 
 
 
 
 
 
1179
  }
1180
  return correcciones.get(nombre, nombre)
1181
 
 
1195
  y=df[columna],
1196
  name=columna,
1197
  mode='lines+markers',
1198
+ line=dict(
1199
+ color=COLORES.get(columna, '#000000'),
1200
+ width=3
1201
+ ),
1202
  marker=dict(size=8),
1203
  hovertemplate=f'<b>{columna}</b>: %{{y:{formato or ".2f"}}}<extra></extra>'
1204
  ))
 
1209
  xaxis_title='Periodo',
1210
  hovermode='x unified',
1211
  template='plotly_white',
1212
+ legend=dict(
1213
+ orientation="h",
1214
+ yanchor="bottom",
1215
+ y=1.02,
1216
+ xanchor="right",
1217
+ x=1
1218
+ ),
1219
+ height=500
1220
  )
1221
 
1222
  if formato:
 
1225
  return fig
1226
 
1227
  def crear_radar_plot(dfs):
1228
+ metricas = {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1229
 
1230
+ try:
1231
+ metricas['Desempleo'] = dfs['desempleo']['Total'].iloc[-1]
1232
+ metricas['Informalidad'] = dfs['informal']['Total'].iloc[-1]
1233
+ metricas['Actividad'] = dfs['actividad']['Total'].iloc[-1]
1234
+ metricas['Brecha Salarial'] = ((dfs['ingresos']['Hombres'].iloc[-1] -
1235
+ dfs['ingresos']['Mujeres'].iloc[-1]) /
1236
+ dfs['ingresos']['Hombres'].iloc[-1]) * 100
1237
+ except (KeyError, IndexError, ZeroDivisionError) as e:
1238
+ print(f"Error al generar radar plot: {str(e)}")
1239
  return go.Figure()
 
 
 
 
1240
 
1241
+ categories = list(metricas.keys())
1242
+ values = list(metricas.values())
1243
+
1244
+ fig = go.Figure()
1245
+
1246
+ fig.add_trace(go.Scatterpolar(
1247
+ r=values + [values[0]],
1248
+ theta=categories + [categories[0]],
1249
+ fill='toself',
1250
+ fillcolor='rgba(142, 68, 173, 0.2)',
1251
+ line=dict(color=COLORES['Brecha'], width=2),
1252
+ name='Indicadores'
1253
+ ))
1254
 
1255
  fig.update_layout(
1256
+ polar=dict(
1257
+ radialaxis=dict(visible=True, range=[0, 100], tickfont=dict(size=12)),
1258
+ angularaxis=dict(rotation=90, direction='clockwise', tickfont=dict(size=14))
1259
+ ),
1260
+ title=dict(text='Radar de Indicadores Laborales', x=0.5, font=dict(size=20)),
1261
+ showlegend=False,
1262
+ height=500
1263
  )
1264
 
 
1265
  return fig
1266
 
1267
+ def analisis_comparativo_desempleo():
1268
+ datos = []
1269
 
 
 
1270
  for ciudad, data in cities_data.items():
1271
  nombre = normalizar_nombres_ciudades(ciudad)
1272
+ df = procesar_dataframe(data['desempleo_trimestral'],
1273
+ ["Trimestre", "Total", "Hombres", "Mujeres"])
1274
  if not df.empty:
1275
+ ultimo_valor = df['Total'].iloc[-1]
1276
+ datos.append({'Ciudad': nombre, 'Desempleo': ultimo_valor})
1277
 
1278
+ if not datos:
1279
+ return go.Figure()
1280
+
1281
+ df_comparativo = pd.DataFrame(datos).sort_values('Desempleo', ascending=False)
1282
+
1283
+ fig = px.bar(df_comparativo,
1284
+ x='Ciudad',
1285
+ y='Desempleo',
1286
+ color='Desempleo',
1287
+ color_continuous_scale='Bluered',
1288
+ text_auto='.1f%',
1289
+ title='Comparación de Tasa de Desempleo entre Ciudades')
 
 
1290
 
1291
+ fig.update_layout(
1292
+ xaxis_title='',
1293
+ yaxis_title='Tasa de Desempleo (%)',
1294
+ coloraxis_showscale=False,
1295
+ xaxis={'categoryorder':'total descending'},
1296
+ height=600
1297
+ )
1298
+
1299
+ return fig
1300
+
1301
+ def generar_analisis_global():
1302
+ figs = []
1303
+
1304
+ # Gráfico comparativo de desempleo
1305
+ figs.append(analisis_comparativo_desempleo())
1306
+
1307
+ # Gráfico de tendencia de ingresos (full width)
1308
  datos_ingresos = []
1309
  for ciudad, data in cities_data.items():
1310
  nombre = normalizar_nombres_ciudades(ciudad)
1311
+ df = procesar_dataframe(data['ingresos_periodo'],
1312
+ ["Periodo", "Total", "Hombres", "Mujeres"])
1313
  if not df.empty:
1314
  df['Ciudad'] = nombre
1315
  datos_ingresos.append(df)
1316
 
1317
  if datos_ingresos:
1318
  df_ingresos = pd.concat(datos_ingresos)
1319
+ fig_ingresos = px.line(df_ingresos,
1320
+ x='Periodo',
1321
+ y='Total',
1322
+ color='Ciudad',
1323
+ title='<b>Evolución Histórica de Ingresos Promedio por Ciudad</b>',
1324
+ markers=True,
1325
+ height=600)
1326
+ fig_ingresos.update_layout(
1327
+ xaxis_title='Periodo',
1328
+ yaxis_title='Ingresos (Soles)',
1329
+ legend=dict(title='Ciudades'),
1330
+ margin=dict(l=50, r=50, t=80, b=50)
1331
  )
1332
  figs.append(fig_ingresos)
1333
  else:
1334
  figs.append(go.Figure())
1335
 
1336
+ # Gráfico de brecha salarial (full width)
1337
  datos_brecha = []
1338
  for ciudad, data in cities_data.items():
1339
  nombre = normalizar_nombres_ciudades(ciudad)
1340
+ df = procesar_dataframe(data['ingresos_periodo'],
1341
+ ["Periodo", "Total", "Hombres", "Mujeres"])
1342
  if not df.empty:
1343
  df['Brecha'] = (df['Hombres'] - df['Mujeres']) / df['Hombres'].replace(0, np.nan) * 100
1344
  df['Ciudad'] = nombre
 
1346
 
1347
  if datos_brecha:
1348
  df_brecha = pd.concat(datos_brecha)
1349
+ fig_brecha = px.bar(df_brecha,
1350
+ x='Ciudad',
1351
+ y='Brecha',
1352
+ color='Brecha',
1353
+ title='<b>Comparación de Brecha Salarial por Ciudad</b>',
1354
+ text_auto='.1f%',
1355
+ height=600,
1356
+ color_continuous_scale='Viridis')
1357
+
1358
+ fig_brecha.update_layout(
1359
+ xaxis_title='Ciudad',
1360
+ yaxis_title='Brecha Salarial (%)',
1361
+ coloraxis_showscale=False,
1362
+ xaxis={'categoryorder':'total descending'},
1363
+ margin=dict(l=50, r=50, t=80, b=150),
1364
+ uniformtext_minsize=8,
1365
+ uniformtext_mode='hide'
1366
  )
1367
  figs.append(fig_brecha)
1368
  else:
 
1372
 
1373
  def actualizar_graficos(ciudad):
1374
  data = cities_data[ciudad]
 
1375
 
1376
  dfs = {
1377
  'desempleo': procesar_dataframe(data['desempleo_trimestral'], ["Trimestre", "Total", "Hombres", "Mujeres"]),
 
1381
  }
1382
 
1383
  return [
 
1384
  crear_grafico_lineas(dfs['desempleo'], "Tasa de Desempleo", "%", ".1f"),
1385
  crear_grafico_lineas(dfs['ingresos'], "Ingresos Promedio", "Soles", ".0f"),
1386
  crear_grafico_lineas(dfs['informal'], "Tasa de Informalidad", "%", ".1f"),
1387
  crear_grafico_lineas(dfs['actividad'], "Tasa de Actividad", "%", ".1f"),
1388
+ crear_radar_plot(dfs),
1389
  crear_grafico_lineas(dfs['ingresos'].assign(
1390
  Brecha=lambda x: (x['Hombres'] - x['Mujeres']) / x['Hombres'].replace(0, np.nan) * 100
1391
+ ), "Brecha Salarial", "%", ".1f")
1392
  ]
1393
 
1394
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), css="""
 
 
1395
  .gradio-container {background-color: #f8f9fa}
1396
+ .plot-container {margin: 20px 0}
1397
+ """) as app:
 
 
 
1398
 
1399
+ gr.Markdown("# 📊 Dashboard Analítico del Mercado Laboral Peruano")
1400
 
1401
+ with gr.Row():
1402
+ ciudad = gr.Dropdown(
1403
+ list(cities_data.keys()),
1404
+ label="Seleccionar Ciudad",
1405
+ value="Chimbote",
1406
+ interactive=True
1407
+ )
1408
 
1409
  with gr.Tab("Análisis por Ciudad"):
1410
+ with gr.Row():
1411
+ desempleo_plot = Plot(label="Tasa de Desempleo")
1412
+ with gr.Row():
1413
+ ingresos_plot = Plot(label="Ingresos Promedio")
1414
+ with gr.Row():
1415
+ informalidad_plot = Plot(label="Tasa de Informalidad")
1416
+ with gr.Row():
1417
+ actividad_plot = Plot(label="Tasa de Actividad")
1418
+ with gr.Row():
1419
+ radar_plot = Plot(label="Radar de Indicadores")
1420
+ with gr.Row():
1421
+ brecha_plot = Plot(label="Brecha Salarial")
 
 
 
 
1422
 
1423
  with gr.Tab("Análisis Comparativo"):
1424
+ with gr.Row():
1425
+ global_desempleo = Plot(label="Ranking de Desempleo")
1426
+ with gr.Row():
1427
+ global_ingresos = Plot(label="Evolución de Ingresos")
1428
+ with gr.Row():
1429
+ global_brecha = Plot(label="Comparación de Brecha Salarial")
1430
+ with gr.Row():
1431
+ global_btn = gr.Button("Actualizar Datos", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
1432
 
1433
+ # Eventos
1434
  ciudad.change(
1435
  fn=actualizar_graficos,
1436
  inputs=ciudad,
1437
+ outputs=[desempleo_plot, ingresos_plot, informalidad_plot, actividad_plot, radar_plot, brecha_plot]
1438
+ )
1439
+
1440
+ global_btn.click(
1441
+ fn=generar_analisis_global,
1442
+ inputs=[],
1443
+ outputs=[global_desempleo, global_ingresos, global_brecha]
1444
  )
1445
 
1446
+ app.launch(debug=True)