Clase 2 — Listas, funciones y numpy#

Python y Políticas Públicas


Contenidos#

  1. Listas: creación, indexing y operaciones

  2. Diccionarios

  3. Funciones

  4. Introducción a numpy

  5. Ejercicio integrador


1. Listas#

Una lista es una colección ordenada y mutable de elementos. Es una de las estructuras de datos más usadas en Python.

# Crear listas
provincias = ["Buenos Aires", "Córdoba", "Santa Fe", "Mendoza", "Tucumán"]
tasas_desempleo = [8.2, 7.5, 9.1, 6.8, 11.3]  # % por provincia
datos_mixtos = ["Buenos Aires", 8.2, True, 2023]  # se pueden mezclar tipos

print(provincias)
print(f"Cantidad de provincias: {len(provincias)}")
['Buenos Aires', 'Córdoba', 'Santa Fe', 'Mendoza', 'Tucumán']
Cantidad de provincias: 5
import matplotlib as mpl
import matplotlib.pyplot as plt

# --- Paleta de identidad del curso ---
C = ['#2A6496', '#E07B3F', '#3D9970', '#8E5EA2', '#C0A830', '#637A8A']

mpl.rcParams.update({
    'figure.figsize'       : (10, 5),
    'font.size'            : 11,
    'axes.titlesize'       : 12,
    'axes.titleweight'     : 'normal',
    'axes.spines.top'      : False,
    'axes.spines.right'    : False,
    'legend.frameon'       : False,
    'axes.prop_cycle'      : mpl.cycler(color=C),
    'figure.dpi'           : 110,
})

def tit(ax, t, **kw):
    """Título sin negrita, alineado a la izquierda."""
    ax.set_title(t, loc='left', fontweight='normal', **kw)
# Indexing: acceder a elementos por posición (empieza en 0)
print(provincias[0])   # primer elemento
print(provincias[-1])  # último elemento
print(provincias[1:3]) # slicing: elementos 1 y 2 (no incluye el 3)
print(provincias[:2])  # primeros dos
print(provincias[2:])  # desde el tercero hasta el final
Buenos Aires
Tucumán
['Córdoba', 'Santa Fe']
['Buenos Aires', 'Córdoba']
['Santa Fe', 'Mendoza', 'Tucumán']
# Operaciones sobre listas
tasas = [8.2, 7.5, 9.1, 6.8, 11.3]

tasas.append(10.2)     # agregar al final
tasas.insert(0, 5.5)   # insertar en posición 0
tasas.remove(9.1)      # eliminar primer elemento con ese valor
tasas.sort()           # ordenar (modifica la lista)

print(tasas)
print(f"Mínimo: {min(tasas)}, Máximo: {max(tasas)}, Suma: {sum(tasas):.1f}")
[5.5, 6.8, 7.5, 8.2, 10.2, 11.3]
Mínimo: 5.5, Máximo: 11.3, Suma: 49.5

2. Diccionarios#

Un diccionario almacena pares clave: valor. Es ideal para representar registros o filas de datos.

# Un programa social como diccionario
programa = {
    "nombre": "Asignación Universal por Hijo",
    "organismo": "ANSES",
    "beneficiarios": 4_200_000,
    "monto_mensual": 42_000,
    "activo": True
}

# Acceder a valores
print(programa["nombre"])
print(programa.get("beneficiarios", 0))  # get() no falla si la clave no existe

# Modificar y agregar
programa["monto_mensual"] = 48_000
programa["anio_inicio"] = 2009

# Iterar
for clave, valor in programa.items():
    print(f"  {clave}: {valor}")
Asignación Universal por Hijo
4200000
  nombre: Asignación Universal por Hijo
  organismo: ANSES
  beneficiarios: 4200000
  monto_mensual: 48000
  activo: True
  anio_inicio: 2009
# Lista de diccionarios: estructura muy común para tablas de datos
programas = [
    {"nombre": "AUH",       "beneficiarios": 4_200_000, "organismo": "ANSES"},
    {"nombre": "Progresar", "beneficiarios": 1_100_000, "organismo": "ANSES"},
    {"nombre": "Potenciar", "beneficiarios": 1_300_000, "organismo": "MDS"},
]

total_beneficiarios = sum(p["beneficiarios"] for p in programas)
print(f"Total de beneficiarios: {total_beneficiarios:,}")

# Filtrar programas de ANSES
anses = [p["nombre"] for p in programas if p["organismo"] == "ANSES"]
print(f"Programas de ANSES: {anses}")
Total de beneficiarios: 6,600,000
Programas de ANSES: ['AUH', 'Progresar']

3. Funciones#

Una función es un bloque de código reutilizable que realiza una tarea específica. Usar funciones hace el código más limpio, modular y fácil de mantener.

# Definición básica
def calcular_tasa_cobertura(poblacion_total, poblacion_cubierta):
    """Devuelve la tasa de cobertura en porcentaje."""
    return (poblacion_cubierta / poblacion_total) * 100

# Uso
tasa = calcular_tasa_cobertura(8_500_000, 7_820_000)
print(f"Tasa de cobertura: {tasa:.1f}%")
Tasa de cobertura: 92.0%
# Argumentos por defecto
def clasificar_tasa(tasa, umbral_alto=80, umbral_medio=60):
    """Clasifica una tasa según umbrales configurables."""
    if tasa >= umbral_alto:
        return "alta"
    elif tasa >= umbral_medio:
        return "media"
    else:
        return "baja"

print(clasificar_tasa(92.0))           # usa umbrales por defecto
print(clasificar_tasa(65.0, umbral_alto=90, umbral_medio=70))  # umbrales custom
alta
baja
# Devolver múltiples valores
def estadisticas_basicas(lista):
    """Devuelve media, mínimo y máximo de una lista."""
    media = sum(lista) / len(lista)
    return media, min(lista), max(lista)

tasas = [8.2, 7.5, 9.1, 6.8, 11.3, 10.2]
media, minimo, maximo = estadisticas_basicas(tasas)
print(f"Media: {media:.2f} | Mínimo: {minimo} | Máximo: {maximo}")
Media: 8.85 | Mínimo: 6.8 | Máximo: 11.3

4. Introducción a numpy#

numpy es la librería fundamental para cómputo numérico en Python. Sus arrays son mucho más eficientes que las listas de Python para operaciones matemáticas.

import numpy as np  # convención: importar como np
# Crear arrays
tasas = np.array([8.2, 7.5, 9.1, 6.8, 11.3, 10.2, 8.9, 7.1])

print(f"Array: {tasas}")
print(f"Tipo: {tasas.dtype}")
print(f"Forma: {tasas.shape}")
print(f"Longitud: {len(tasas)}")
Array: [ 8.2  7.5  9.1  6.8 11.3 10.2  8.9  7.1]
Tipo: float64
Forma: (8,)
Longitud: 8
# Operaciones vectorizadas (se aplican a todos los elementos a la vez)
tasas = np.array([8.2, 7.5, 9.1, 6.8, 11.3, 10.2, 8.9, 7.1])

# Estadísticas
print(f"Media:    {tasas.mean():.2f}")
print(f"Mediana:  {np.median(tasas):.2f}")
print(f"Desvío:   {tasas.std():.2f}")
print(f"Mínimo:   {tasas.min()}")
print(f"Máximo:   {tasas.max()}")

# Operaciones aritméticas sobre todo el array
tasas_decimal = tasas / 100
print(f"\nEn decimal: {tasas_decimal}")
Media:    8.64
Mediana:  8.55
Desvío:   1.46
Mínimo:   6.8
Máximo:   11.3

En decimal: [0.082 0.075 0.091 0.068 0.113 0.102 0.089 0.071]
# Filtrado con condiciones booleanas
tasas = np.array([8.2, 7.5, 9.1, 6.8, 11.3, 10.2, 8.9, 7.1])

altas = tasas[tasas > 9]  # tasas mayores a 9%
print(f"Tasas altas (> 9%): {altas}")
print(f"Cantidad: {len(altas)} de {len(tasas)} regiones")
Tasas altas (> 9%): [ 9.1 11.3 10.2]
Cantidad: 3 de 8 regiones
# Arrays 2D: como una tabla/matriz
# Filas = años (2021, 2022, 2023), Columnas = regiones (NOA, NEA, Centro, Cuyo, Patagonia)
desempleo = np.array([
    [10.1, 11.5,  8.3,  7.2,  6.8],  # 2021
    [ 9.8, 10.9,  7.9,  6.5,  6.1],  # 2022
    [ 9.2, 10.2,  7.5,  6.8,  5.9],  # 2023
])

print(f"Forma: {desempleo.shape}")  # (3 filas, 5 columnas)
print(f"Media por región: {desempleo.mean(axis=0).round(2)}")   # a lo largo de filas
print(f"Media por año:    {desempleo.mean(axis=1).round(2)}")   # a lo largo de columnas
Forma: (3, 5)
Media por región: [ 9.7  10.87  7.9   6.83  6.27]
Media por año:    [8.78 8.24 7.92]

5. Ejercicio integrador#

Combinamos funciones, numpy, listas y for.

Contexto: Tenés datos de pobreza para 6 provincias en tres años consecutivos. Querés:

  1. Calcular la variación interanual de la tasa de pobreza para cada provincia.

  2. Identificar qué provincias mejoraron (tasa bajó) y cuáles empeoraron.

  3. Calcular el promedio nacional de mejora/deterioro.

import numpy as np

provincias = ["Buenos Aires", "Córdoba", "Santa Fe", "Mendoza", "Tucumán", "Salta"]

# Tasas de pobreza (%) por año
pobreza_2021 = np.array([42.3, 38.1, 39.7, 34.2, 48.6, 52.1])
pobreza_2022 = np.array([40.1, 36.8, 38.2, 33.5, 46.9, 50.7])
pobreza_2023 = np.array([38.9, 35.4, 37.1, 32.8, 45.2, 49.3])


def calcular_variacion(tasa_anterior, tasa_actual):
    """Devuelve la variación en puntos porcentuales (negativo = mejora)."""
    return tasa_actual - tasa_anterior


# Variaciones
var_21_22 = calcular_variacion(pobreza_2021, pobreza_2022)
var_22_23 = calcular_variacion(pobreza_2022, pobreza_2023)

print("=" * 60)
print(f"{'Provincia':<20} {'2021':>6} {'2022':>6} {'2023':>6} {'Var 21-22':>10} {'Tendencia':>12}")
print("-" * 60)

for i, provincia in enumerate(provincias):
    variacion = var_22_23[i]
    tendencia = "↓ mejora" if variacion < 0 else "↑ empeora"
    print(f"{provincia:<20} {pobreza_2021[i]:>6.1f} {pobreza_2022[i]:>6.1f} {pobreza_2023[i]:>6.1f} {variacion:>+10.1f} {tendencia:>12}")

print("-" * 60)
print(f"Variación promedio 2022-2023: {var_22_23.mean():+.2f} pp")
print(f"Provincias que mejoraron: {(var_22_23 < 0).sum()} de {len(provincias)}")
============================================================
Provincia              2021   2022   2023  Var 21-22    Tendencia
------------------------------------------------------------
Buenos Aires           42.3   40.1   38.9       -1.2     ↓ mejora
Córdoba                38.1   36.8   35.4       -1.4     ↓ mejora
Santa Fe               39.7   38.2   37.1       -1.1     ↓ mejora
Mendoza                34.2   33.5   32.8       -0.7     ↓ mejora
Tucumán                48.6   46.9   45.2       -1.7     ↓ mejora
Salta                  52.1   50.7   49.3       -1.4     ↓ mejora
------------------------------------------------------------
Variación promedio 2022-2023: -1.25 pp
Provincias que mejoraron: 6 de 6

Ejercicios#

Ejercicio 1#

Creá una función indice_desarrollo(salud, educacion, ingresos) que calcule el promedio de los tres parámetros (todos en escala 0-100). Aplicala a las siguientes regiones usando un for:

regiones = [
    {"nombre": "NOA",       "salud": 62, "educacion": 58, "ingresos": 45},
    {"nombre": "NEA",       "salud": 60, "educacion": 55, "ingresos": 42},
    {"nombre": "Centro",    "salud": 78, "educacion": 80, "ingresos": 75},
    {"nombre": "Cuyo",      "salud": 72, "educacion": 70, "ingresos": 65},
    {"nombre": "Patagonia", "salud": 80, "educacion": 77, "ingresos": 82},
]

Imprimí el índice de cada región y al final la región con el índice más alto.

# Tu solución aquí

Ejercicio 2#

Usá numpy para analizar la siguiente serie de presupuesto ejecutado mensualmente (en millones de pesos) durante un año:

ejecucion = np.array([820, 910, 880, 1050, 970, 1200, 1180, 1150, 1300, 1250, 1400, 1350])

Calculá: media, mediana, desvío estándar, y el porcentaje de meses que superaron la media.

import numpy as np
ejecucion = np.array([820, 910, 880, 1050, 970, 1200, 1180, 1150, 1300, 1250, 1400, 1350])
# Tu solución aquí