Ejemplos pandas

ventas_alimentacion

import pandas as pd

df = pd.read_csv("ventas_alimentacion.csv", index_col=0)
print(df)

# Estadísticas por ciudad
print(df.sum())    # total ventas por ciudad
print(df.mean())   # media por ciudad
print(df.max())    # máximo por ciudad


datos = {
    "Madrid":    [12450, 8760, 11230, 9340, 14560, 10870, 6540, 7890],
    "Barcelona": [9870,  7540, 8650,  7120, 11230, 12340, 5120, 6540],
    "Valencia":  [7340,  5980, 6780,  8450, 8760,  7650,  4870, 5230],
    "Sevilla":   [8920,  6120, 7450,  9210, 9870,  8430,  5340, 4980],
    "Zaragoza":  [4120,  3870, 4560,  3980, 5120,  3760,  2980, 3240],
    "Bilbao":    [5630,  4920, 6120,  4760, 7340,  9120,  3870, 4560],
    "Málaga":    [6780,  4560, 5340,  7890, 6540,  8760,  4120, 3870],
    "Murcia":    [3940,  3210, 4120,  5340, 4870,  4230,  2760, 2980],
}

indice = [
    "Aceite de oliva",
    "Pan y bollería",
    "Leche y lácteos",
    "Frutas y verduras",
    "Carne y charcutería",
    "Pescado y marisco",
    "Pasta, arroz y legumbres",
    "Conservas y enlatados",
]

df = pd.DataFrame(datos, index=indice)
print(df)

import pandas as pd

# ─────────────────────────────────────────────
#  DATAFRAME DE EJEMPLO
# ─────────────────────────────────────────────
data = {
    "Madrid":    [12450, 8760, 11230,  9340, 14560, 10870],
    "Barcelona": [ 9870, 7540,  8650,  7120, 11230, 12340],
    "Valencia":  [ 7340, 5980,  6780,  8450,  8760,  7650],
    "Sevilla":   [ 8920, 6120,  7450,  9210,  9870,  8430],
    "Bilbao":    [ 5630, 4920,  6120,  4760,  7340,  9120],
    "Murcia":    [ 3940, 3210,  4120,  5340,  4870,  4230],
}

indice = [
    "Aceite de oliva",
    "Pan y bollería",
    "Leche y lácteos",
    "Frutas y verduras",
    "Carne y charcutería",
    "Pescado y marisco",
]

df = pd.DataFrame(data, index=indice)

print(df)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 1 — .loc[]  →  celda exacta por nombre
# ══════════════════════════════════════════════════════════════════
# .loc usa ETIQUETAS (nombres reales de filas y columnas).
# Sintaxis: df.loc["nombre_fila", "nombre_columna"]
resultado = df.loc["Leche y lácteos", "Madrid"]
print("1) .loc celda exacta:")
print(resultado)          # 11230
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 2 — .iloc[]  →  celda exacta por posición numérica
# ══════════════════════════════════════════════════════════════════
# .iloc usa POSICIONES enteras (0-based, igual que las listas).
# Fila 1 = "Pan y bollería", columna 2 = "Valencia"
resultado = df.iloc[1, 2]
print("2) .iloc celda exacta:")
print(resultado)          # 5980
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 3 — df["columna"]  →  columna completa (una Serie)
# ══════════════════════════════════════════════════════════════════
# Con un solo corchete y el nombre de columna obtienes una Serie.
# La Serie conserva el índice original del DataFrame.
resultado = df["Barcelona"]
print("3) Columna completa con df['col']:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 4 — .loc["fila"]  →  fila completa por nombre
# ══════════════════════════════════════════════════════════════════
# Al pasar solo un nombre de fila, .loc devuelve una Serie
# donde el índice son los nombres de las columnas.
resultado = df.loc["Frutas y verduras"]
print("4) Fila completa con .loc:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 5 — .iloc[:, col]  →  columna completa por posición
# ══════════════════════════════════════════════════════════════════
# El ":" significa "todas las filas".
# La columna 3 corresponde a "Sevilla" (0=Madrid, 1=Barcelona, ...)
resultado = df.iloc[:, 3]
print("5) Columna por posición con .iloc[:, 3]:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 6 — .loc[inicio:fin]  →  rango de filas por nombre
# ══════════════════════════════════════════════════════════════════
# Con .loc los rangos son INCLUSIVOS en ambos extremos,
# es decir, se incluyen tanto "Pan y bollería" como "Frutas y verduras".
resultado = df.loc["Pan y bollería":"Frutas y verduras"]
print("6) Rango de filas con .loc (inclusivo):")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 7 — .iloc[inicio:fin]  →  rango de filas por posición
# ══════════════════════════════════════════════════════════════════
# Con .iloc los rangos son EXCLUSIVOS en el extremo derecho,
# igual que los slices de Python. iloc[2:5] devuelve filas 2, 3 y 4.
resultado = df.iloc[2:5]
print("7) Rango de filas con .iloc (exclusivo en el extremo derecho):")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 8 — .iloc[f1:f2, c1:c2]  →  submatriz por posición
# ══════════════════════════════════════════════════════════════════
# Selecciona filas 0, 1, 2  (0:3 → exclusivo en 3)
# y columnas 1, 2, 3        (1:4 → exclusivo en 4)
resultado = df.iloc[0:3, 1:4]
print("8) Submatriz con .iloc[0:3, 1:4]:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 9 — .loc[rango_filas, lista_columnas]
# ══════════════════════════════════════════════════════════════════
# Combina un rango de filas (por nombre) con una lista de columnas
# específicas. Muy útil para extraer subconjuntos concretos.
resultado = df.loc["Aceite de oliva":"Leche y lácteos", ["Madrid", "Bilbao"]]
print("9) Rango de filas + columnas específicas con .loc:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 10 — df[df["col"] > valor]  →  filtrado booleano
# ══════════════════════════════════════════════════════════════════
# La expresión df["Madrid"] > 10000 genera una Serie de True/False.
# Al pasarla al DataFrame, devuelve solo las filas donde es True.
resultado = df[df["Madrid"] > 10000]
print("10) Máscara booleana — ventas en Madrid > 10.000 €:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 11 — .loc[condición, columnas]  →  filtro + selección
# ══════════════════════════════════════════════════════════════════
# Combina un filtro booleano con selección de columnas concretas.
# Primero filtra las filas y luego escoge qué columnas mostrar.
resultado = df.loc[df["Barcelona"] > 9000, ["Barcelona", "Madrid"]]
print("11) .loc con condición y selección de columnas:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 12 — df[["c1", "c2", ...]]  →  varias columnas a la vez
# ══════════════════════════════════════════════════════════════════
# Con DOBLE corchete se pasa una lista de nombres.
# El resultado es un DataFrame (no una Serie), aunque elijas 1 columna.
resultado = df[["Madrid", "Sevilla", "Murcia"]]
print("12) Varias columnas con doble corchete:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 13 — .iat[]  →  celda por posición (versión rápida)
# ══════════════════════════════════════════════════════════════════
# .iat es equivalente a .iloc para UN ÚNICO valor escalar.
# Es más eficiente que .iloc en DataFrames grandes porque
# no construye objetos intermedios.
resultado = df.iat[4, 0]
print("13) .iat — celda por posición (rápido):")
print(resultado)          # 14560  (fila 4 = "Carne", col 0 = "Madrid")
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 14 — .at[]  →  celda por etiqueta (versión rápida)
# ══════════════════════════════════════════════════════════════════
# .at es equivalente a .loc para UN ÚNICO valor escalar.
# Más rápido que .loc cuando solo necesitas un dato concreto.
resultado = df.at["Pescado y marisco", "Bilbao"]
print("14) .at — celda por etiqueta (rápido):")
print(resultado)          # 9120

import pandas as pd

# ─────────────────────────────────────────────
#  DATAFRAME DE EJEMPLO
# ─────────────────────────────────────────────
data = {
    "Madrid":    [12450, 8760, 11230,  9340, 14560, 10870],
    "Barcelona": [ 9870, 7540,  8650,  7120, 11230, 12340],
    "Valencia":  [ 7340, 5980,  6780,  8450,  8760,  7650],
    "Sevilla":   [ 8920, 6120,  7450,  9210,  9870,  8430],
    "Bilbao":    [ 5630, 4920,  6120,  4760,  7340,  9120],
    "Murcia":    [ 3940, 3210,  4120,  5340,  4870,  4230],
}

indice = [
    "Aceite de oliva",
    "Pan y bollería",
    "Leche y lácteos",
    "Frutas y verduras",
    "Carne y charcutería",
    "Pescado y marisco",
]

df = pd.DataFrame(data, index=indice)

print(df)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 1 — df["col"] > valor  →  máscara booleana simple
# ══════════════════════════════════════════════════════════════════
# Una comparación sobre una columna devuelve una Serie de True/False.
# Al pasarla al DataFrame, actúa como "filtro de filas".
# Solo se muestran las filas donde la condición es verdadera.
mascara = df["Madrid"] > 10000
resultado = df[mascara]
print("1) Máscara booleana simple — Madrid > 10 000 €:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 2 — & (AND)  →  dos condiciones simultáneas
# ══════════════════════════════════════════════════════════════════
# Para combinar condiciones usa & (AND) o | (OR).
# IMPORTANTE: cada condición debe ir entre paréntesis porque
# & tiene mayor precedencia que > y <.
resultado = df[(df["Madrid"] > 9000) & (df["Barcelona"] > 9000)]
print("2) Dos condiciones con & (AND) — Madrid > 9 000 y Barcelona > 9 000:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 3 — | (OR)  →  al menos una condición verdadera
# ══════════════════════════════════════════════════════════════════
# Con | basta con que UNA de las condiciones sea True.
# Aquí: filas donde Bilbao supera 8 000 O Murcia supera 5 000.
resultado = df[(df["Bilbao"] > 8000) | (df["Murcia"] > 5000)]
print("3) Dos condiciones con | (OR) — Bilbao > 8 000 o Murcia > 5 000:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 4 — ~  →  negación de una máscara
# ══════════════════════════════════════════════════════════════════
# El operador ~ invierte una máscara booleana (True → False y viceversa).
# Equivale al NOT lógico: devuelve las filas que NO cumplen la condición.
resultado = df[~(df["Valencia"] > 7000)]
print("4) Negación con ~ — filas donde Valencia NO supera 7 000 €:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 5 — .isin()  →  filtrar por lista de valores
# ══════════════════════════════════════════════════════════════════
# .isin(lista) devuelve True en las filas cuyo valor está en la lista.
# Muy útil cuando tienes un conjunto de etiquetas permitidas.
categorias_interes = ["Aceite de oliva", "Carne y charcutería", "Pescado y marisco"]
resultado = df[df.index.isin(categorias_interes)]
print("5) .isin() — solo categorías de interés:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 6 — .query()  →  filtrar con expresión de texto
# ══════════════════════════════════════════════════════════════════
# .query() acepta una cadena de texto con la condición en lenguaje
# casi natural. Más legible para condiciones complejas.
# Nota: si el nombre de columna tiene espacios, usa backticks (`col`).
resultado = df.query("Madrid > 10000 and Sevilla > 8000")
print("6) .query() — Madrid > 10 000 y Sevilla > 8 000:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 7 — .filter(items=)  →  seleccionar columnas por nombre
# ══════════════════════════════════════════════════════════════════
# .filter() selecciona columnas (o filas con axis=0) por nombre exacto.
# No filtra por valores, sino por NOMBRE de columna.
resultado = df.filter(items=["Madrid", "Barcelona", "Murcia"])
print("7) .filter(items=) — columnas Madrid, Barcelona y Murcia:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 8 — .filter(like=)  →  columnas cuyo nombre contiene texto
# ══════════════════════════════════════════════════════════════════
# like= selecciona columnas cuyo nombre CONTIENE la subcadena dada.
# axis=1 indica que buscamos en columnas; axis=0 buscaría en el índice.
resultado = df.filter(like="a", axis=1)   # columnas que contienen "a"
print("8) .filter(like='a') — columnas que contienen la letra 'a':")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 9 — .filter(regex=)  →  columnas por expresión regular
# ══════════════════════════════════════════════════════════════════
# regex= permite filtrar columnas cuyo nombre cumple un patrón regex.
# Aquí seleccionamos columnas que empiezan por 'M', 'B' o 'S'.
resultado = df.filter(regex="^(M|B|S)", axis=1)
print("9) .filter(regex=) — columnas que empiezan por M, B o S:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 10 — .loc[condición, columnas]  →  filtro fila + columnas
# ══════════════════════════════════════════════════════════════════
# .loc admite una máscara booleana como selector de filas Y una lista
# de columnas como segundo argumento. El resultado es un sub-DataFrame.
resultado = df.loc[df["Bilbao"] > 6000, ["Bilbao", "Madrid", "Murcia"]]
print("10) .loc con condición + columnas — Bilbao > 6 000, ver Bilbao/Madrid/Murcia:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 11 — .where()  →  mantiene forma, enmascara con NaN
# ══════════════════════════════════════════════════════════════════
# A diferencia de los filtros anteriores, .where() conserva el shape
# original del DataFrame. Las celdas que NO cumplen la condición
# se sustituyen por NaN (o por el valor que indiques en `other=`).
resultado = df.where(df > 8000)
print("11) .where(df > 8000) — valores < 8 000 sustituidos por NaN:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 12 — .mask()  →  inverso de .where()
# ══════════════════════════════════════════════════════════════════
# .mask() es el opuesto de .where(): enmascara con NaN las celdas
# que SÍ cumplen la condición, manteniendo las que no la cumplen.
resultado = df.mask(df > 8000)
print("12) .mask(df > 8000) — valores > 8 000 sustituidos por NaN:")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 13 — filtro por índice con .str  →  texto en el índice
# ══════════════════════════════════════════════════════════════════
# Si el índice es de tipo cadena, puedes usar .str para filtrarlo.
# .str.contains() busca una subcadena; .str.startswith() un prefijo.
resultado = df[df.index.str.contains("y")]
print("13) Filtro de texto en el índice — categorías que contienen 'y':")
print(resultado)
print()


# ══════════════════════════════════════════════════════════════════
#  MÉTODO 14 — .nlargest() / .nsmallest()  →  top N por columna
# ══════════════════════════════════════════════════════════════════
# .nlargest(n, columna) devuelve las n filas con mayor valor en
# la columna indicada, ordenadas de mayor a menor.
# .nsmallest(n, columna) hace lo mismo para los menores valores.
resultado = df.nlargest(3, "Madrid")
print("14) .nlargest(3, 'Madrid') — top 3 categorías en Madrid:")
print(resultado)
print()

resultado = df.nsmallest(3, "Murcia")
print("    .nsmallest(3, 'Murcia') — bottom 3 categorías en Murcia:")
print(resultado)
print()

Ejemplo Outliers

import numpy as np          # Para cálculos matemáticos con arrays
import pandas as pd         # Para trabajar con tablas de datos (DataFrames)
import matplotlib.pyplot as plt  # Para crear gráficos
                            # Alternativa moderna a matplotlib: import seaborn as sns (más bonito por defecto)

# Semilla para reproducibilidad (siempre obtendremos los mismos resultados)
# Alternativa: omitirla si quieres datos distintos cada vez que ejecutes el código
np.random.seed(42)

# Creamos 97 datos normales (media=50, desviacion tipica=8)
# loc = centro de la campana, scale = ancho, size = número de valores generados
# Alternativa con pandas: pd.Series(np.random.normal(50, 8, 97))
datos_normales = np.random.normal(loc=50, scale=8, size=97)

# Anadimos 3 outliers evidentes
# Son valores que claramente se salen del rango normal (50±8 → esperamos valores entre ~26 y ~74)
# Alternativa: outliers_manuales = np.array([datos_normales.mean() - 6*datos_normales.std(), ...])
outliers_manuales = np.array([5, 95, 102])

# Combinamos todo en un array
# np.concatenate une dos arrays como si pegases dos listas una detrás de otra
# Alternativa con listas puras: datos = datos_normales.tolist() + outliers_manuales.tolist()
datos = np.concatenate([datos_normales, outliers_manuales])

# len() cuenta el número total de elementos. Para un array NumPy también puedes usar datos.shape[0]
print(f'Total de datos: {len(datos)}')
# .min() y .max() son métodos de NumPy. Alternativa: np.min(datos), np.max(datos)
print(f'Minimo: {datos.min():.2f}')   # :.2f → muestra solo 2 decimales
print(f'Maximo: {datos.max():.2f}')

# Calculamos los percentiles 25 y 75 (= Q1 y Q3)
# Percentil 25 significa: el valor por debajo del cual está el 25% de los datos
# Alternativa con pandas: Q1 = pd.Series(datos).quantile(0.25)
Q1 = np.percentile(datos, 25)
Q3 = np.percentile(datos, 75)

# Calculamos el IQR
# IQR = distancia entre el "centro" del 50% de los datos. Cuanto mayor, más dispersos están.
# A diferencia de la sigma, el IQR no se ve afectado por los outliers extremos.
IQR = Q3 - Q1

print(f'Q1 (percentil 25): {Q1:.2f}')
print(f'Q3 (percentil 75): {Q3:.2f}')
print(f'IQR = Q3 - Q1:     {IQR:.2f}')

# Creamos un DataFrame de pandas
# Un DataFrame es como una tabla Excel: filas y columnas con nombre.
# Aquí tiene una sola columna llamada 'valor' con los 100 datos.
# Alternativa: df = pd.DataFrame(datos, columns=['valor'])
df = pd.DataFrame({'valor': datos})


# Funcion reutilizable para detectar outliers con IQR
# Recibe una Serie de pandas y un factor (por defecto 1.5, el estándar de Tukey).
# Aumentar el factor (ej: 3.0) hace la detección más permisiva (menos outliers detectados).
# Alternativa: sklearn.preprocessing.RobustScaler para normalizar eliminando outliers automáticamente
def detectar_outliers_iqr(serie, factor=1.5):
    Q1 = serie.quantile(0.25)   # equivale a np.percentile pero opera sobre Series de pandas
    Q3 = serie.quantile(0.75)
    IQR = Q3 - Q1
    limite_inf = Q1 - factor * IQR  # Por debajo de esto → outlier. Con factor=1.5: regla de Tukey
    limite_sup = Q3 + factor * IQR  # Por encima de esto → outlier
    # El operador | es OR lógico: True si el valor es menor que el límite inferior O mayor que el superior
    # Alternativa: mascara = ~serie.between(limite_inf, limite_sup)
    mascara = (serie < limite_inf) | (serie > limite_sup)
    return mascara, limite_inf, limite_sup  # Devuelve 3 valores a la vez (tupla)


# Usamos la funcion
# Python permite recoger los 3 valores devueltos directamente en 3 variables
# mascara es una Serie de True/False con la misma longitud que df
mascara, lim_inf, lim_sup = detectar_outliers_iqr(df['valor'])

# Anadimos una columna al DataFrame
# df['nueva_columna'] = valores crea una nueva columna. Muy habitual en pandas.
# Alternativa: df = df.assign(es_outlier=mascara)
df['es_outlier'] = mascara

# Ver solo los outliers
# df[condicion] filtra las filas donde la condición es True. Igual que un WHERE en SQL.
# Alternativa más corta: df[df['es_outlier']]  (True/False ya es suficiente, sin == True)
print(df[df['es_outlier'] == True])

# plt.subplots(1, 2) crea una figura con 1 fila y 2 columnas de gráficos (dos gráficos lado a lado)
# figsize=(12, 5) → ancho=12 pulgadas, alto=5 pulgadas
# Alternativa con seaborn: fig, axes = plt.subplots(1, 2) + sns.boxplot(..., ax=axes[0])
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# --- Grafico 1: Diagrama de caja (Boxplot) ---
ax1 = axes[0]
# patch_artist=True → rellena la caja con color (por defecto está vacía)
# boxprops, medianprops → diccionarios para personalizar el estilo visual
# Alternativa más sencilla: pd.Series(datos).plot.box(ax=ax1)
ax1.boxplot(datos, patch_artist=True,
            boxprops=dict(facecolor='lightblue'),
            medianprops=dict(color='red', linewidth=2))
# axhline dibuja una línea horizontal en y=valor. Muy útil para marcar umbrales.
# Alternativa: ax1.fill_betweenx para sombrear la zona válida en vez de marcar los límites
ax1.axhline(y=lim_inf, color='red', linestyle='--', label=f'Limite inf: {lim_inf:.1f}')
ax1.axhline(y=lim_sup, color='red', linestyle='--', label=f'Limite sup: {lim_sup:.1f}')
ax1.set_title('Diagrama de Caja')
ax1.legend()  # Muestra la leyenda con los labels definidos arriba

# --- Grafico 2: Histograma ---
ax2 = axes[1]
# ~ es el operador NOT para arrays booleanos: invierte True↔False
# datos[~mascara] → solo los valores donde mascara es False (= los datos normales)
normales = datos[~mascara]
# mascara.values convierte la Serie de pandas a array NumPy para poder indexar datos con ella
# Alternativa: outs = df[df['es_outlier']]['valor'].values
outs = datos[mascara.values]
# Superponemos dos histogramas en el mismo eje: uno azul (normales) y uno rojo (outliers)
# bins=20 → divide el rango en 20 barras. Más bins = más detalle, menos bins = más suavizado
ax2.hist(normales, bins=20, color='steelblue', label='Datos normales')
ax2.hist(outs, bins=5, color='red', label=f'Outliers ({len(outs)})')
# axvline dibuja líneas verticales (igual que axhline pero en vertical) para marcar los límites
ax2.axvline(lim_inf, color='darkred', linestyle='--')
ax2.axvline(lim_sup, color='darkred', linestyle='--')
ax2.set_title('Histograma con Outliers marcados')
ax2.legend()

# tight_layout() ajusta automáticamente los márgenes para que los gráficos no se solapen
# Alternativa: plt.subplots_adjust(wspace=0.3) para controlar el espacio manualmente
plt.tight_layout()
plt.show()  # Muestra la figura. En Jupyter Notebook no hace falta, se muestra automáticamente.

Soluciones comprension

# Crea una lista con los cuadrados de los números del 1 al 10.

cuadrados = [numero ** 2 for numero in range(1, 11)]
print(cuadrados)
lista = [1.4, 5.6, 9.35]
cuadrados = [numero ** 2 for numero in lista]
print(cuadrados)
# Obtén una lista con los números del 0 al 20 que sean múltiplos de 3.
multiplos3 = [numero for numero in range(0, 21) if numero % 3 == 0]
print(multiplos3)
# Dada la lista ["Ana", "Luis", "Pedro"], obtén una lista con sus longitudes.
lista = ["Ana", "Luis", "Pedro"]
longitudes = [len(cadena) for cadena in lista]
print(longitudes)


# Crear una función fueraNegativos a la que le pasamos una lista y nos devuelve
# solo los positivos fueraNegativos ([3, -1, -7, 5, 0])->[3,5,0]
def fueraNegativos(lista):
    resultado = [numero for numero in lista if numero >= 0]
    return resultado


print(fueraNegativos([3, -1, -7, 5, 0]))


# Crea una función a la que se le pasa un límite y un número y nos devuelve una
# lista con todos los números hasta ese límite que son múltiplos de ese número
# listaMultiplos(10,4)->[4,8]
def listaMultiplos(limite, multiplo):
    resultado = [numero for numero in range(1, limite + 1) if numero % multiplo == 0]
    return resultado


print(listaMultiplos(10, 4))  # [4,8]
print(listaMultiplos(20, 3))  # [3,6,9,12,15,18]


# Crea una función a la que le pasamos un número y nos devuelve una lista
# con la tabla de multiplicar de ese número tablaMultiplicar(7)->[7,14,21,…70]
def tablaMultiplicar(numero):
    resultado = [numero * n for n in range(1, 11)]
    return resultado


def tablaMultiplicar2(numero):
    resultado = [n for n in range(1, numero * 10 + 1) if n % numero == 0]
    return resultado


print(tablaMultiplicar(7))  # [7, 14, 21, 28, 35, 42, 49, 56, 63, 70]
print(tablaMultiplicar2(7))  # [7, 14, 21, 28, 35, 42, 49, 56, 63, 70]


# Crea una función a la que le pasamos una lista de palabras y nos devuelve solo
# las que tengan vocales conVocales([“hola”,”qwfr”,”que”])->[“hola”,”que”]

def tieneVocal(cadena):
    cadena = cadena.lower()
    vocales = "aeiouáéíóúàèìòùü"
    for vocal in vocales:
        if vocal in cadena:
            return True
    return False


print(tieneVocal("hola"))  # True
print(tieneVocal("gjhgjh"))  # False


def conVocales(lista):
    resultado = [cadena for cadena in lista if tieneVocal(cadena)]
    return resultado


print(conVocales(["asasa", "jkhkjhk", "pepe", "sÍ", "üà"]))  # ['asasa', 'pepe']


# Crea una función a la que le pasamos un límite y nos dice los números primos
# hasta ese límite
def esPrimo(numero):
    for i in range(2, numero):
        if numero % i == 0:
            return False
    return True


def primosHasta(limite):
    resultado = [numero for numero in range(1, limite + 1) if esPrimo(numero)]
    return resultado


print(primosHasta(100))

Solución ejercicios

# Definir el algoritmo
# Los pasos que vamos a implementar para resolver el problema
# La 'receta'
# Divide y vencerás: un problema grande se compone de otros más pequeños
# Lo primero es pensar ¿Cömo voy a resolver este problema?

# Cread una función a la que le pasamos una lista de números y nos devuelva una lista
# con el menor y el mayor
# menorMayor([3,1,8,5])->[1,8]

# Cual es el mayor y cual es el menor

# Esta solución es más fácil
def menorMayor(lista):
    ordenada = sorted(lista)
    return [ordenada[0], ordenada[-1]]


# Esta solución es más eficiente, porque ordenar es algo muy costoso
def menorMayor2(lista):
    menor = lista[0]
    mayor = lista[0]
    for numero in lista:
        if numero < menor:
            menor = numero
        if numero > mayor:
            mayor = numero
    return [menor, mayor]


# Esto de aquí hay que evitarlo: No se modifican los parámetros que pasamos
def menorMayor3(lista):
    lista.sort()
    menor = lista.pop(0)
    mayor = lista.pop(-1)
    return [menor, mayor]


print(menorMayor([3, 1, 8, 5]))
print(menorMayor2([3, 1, 8, 5]))

milista = [2, 1, 6, 8, 33, 4, 12, 25]
print(menorMayor3(milista))
print(milista)


# Cread una función a la que le pasamos una lista de nombres y nos devuelve una lista
# con todos los nombres en minúsculas
# minusculas(["Ana","Pep","Iu"])->["ana","pep","iu"]

# Tener un sitio donde guardar el resultado
# recorrer la lista
# como pasar una cadena a minúsculas
def minusculas(lista):
    resultado = []
    for elemento in lista:
        resultado.append(elemento.lower())
    return resultado


print(minusculas(["Ana", "Pep", "Iu"]))


# Cread una función a la que le pasamos una lista de cadenas y nos devuelve una lista
# con las que tengan una longitud par
# longitudPar(["aa","bbb","cccc","ddddd"])->["aa","cccc"]

# Tener un sitio donde guardar el resultado
# recorrer la lista
# Si la longitud es par, lo añado a la lista
def longitudPar(lista):
    resultado = []
    for elemento in lista:
        if len(elemento) % 2 == 0:
            resultado.append(elemento)
    return resultado


print(longitudPar(["aa", "bbb", "cccc", "ddddd"]))

Soluciones ejercicios

# Cread una función a la que le pasamos un cantidad y nos devuelve una lista con
# esa cantidad de la cadena "hola" repetidas
# crearHolas(4)->["Hola","Hola","Hola","Hola"]

def crearHolas(cantidad):
    # devolver una lista con la cadena "Hola" repetida 'cantidad' veces
    resultado = []
    # Tengo añadir la cadena "Hola" a esa lista n veces
    # 1.- Hacer algo n veces for
    # 2.- Añadir una cadena a una lista append
    for i in range(cantidad):
        resultado.append("Hola")

    return resultado


def crearHolas2(cantidad):
    return ["Hola"] * cantidad


print(crearHolas(4))
print(crearHolas2(4))


# tengo la siguiente función que me calcula la media de una lista
def media(lista):
    suma = 0
    for numero in lista:
        suma += numero
    return (suma / len(lista))


# Cread una función mediaAprobados que nos calcule la media pero solo de aquellos números
# que son >=5

def mediaAprobados(lista):
    suma = 0
    cont = 0
    for numero in lista:
        if numero >= 5:
            suma += numero
            cont += 1
    print(suma)
    return (suma / cont)


def mediaAprobados2(lista):
    aprobados = []
    for numero in lista:
        if numero >= 5:
            aprobados.append(numero)
    return media(aprobados)


lista = [1, 8, 3, 4, 5, 6, 2, 8, 9]
calculo = mediaAprobados(lista)
print(calculo)
calculo = mediaAprobados2(lista)
print(calculo)


# Cread una función a la que le pasemos una lista de cadenas y una longitud y nos diga
# cuantas cadenas son mayores de esa longitud
# contarCadenas(["aaa","bbbb","ccccc"],3)->2

def contarCadenas(lista, longitud):
    # una variable donde contar
    cont = 0
    # recorrer la lista de cadenas
    for cadena in lista:
        # Si la cadena tiene una longitud mayor de 'longitud' contarla y si no hago nada
        if len(cadena) > longitud:
            cont += 1
    return cont


print(contarCadenas(["aaa", "bbbb", "ccccc"], 3))
print(contarCadenas(["aaa", "bbbb", "ccccc"], 2))


# Cread una función a la que le pasamos una lista de cadenas y nos devuelve True si
# alguna de las cadenas tiene una 'j'
# tieneJ(["aa","bb"])->False   tieneJ(["aa","bb","ajo"])->True

def tieneJ(lista):
    # recorrer la lista
    for cadena in lista:
        # si la cadena tiene una j devuelvo true si no tiene NO HAGO NADA
        if "j" in cadena:
            return True
    # si al final ninguna ha tenido una j devolvemos false
    return False


print(tieneJ(["aa", "bb"]))
print(tieneJ(["aa", "bb", "ajo"]))


# Crea una función a la que le pasamos una lista de cadenas y me devuelva la más larga
# si hay varias cadenas con la misma longitud, la primera
# masLarga(["aa","eeeee","bbb"])->"eeeee"

# en algún sitio guardaré la cadena más larga
# recorrer la lista
# si la cadena que estoy mirando es más larga que la que ya tengo me quedo con ella

def masLarga(lista):
    larga = ""
    for cadena in lista:
        # Aquí está la magia
        if len(cadena) > len(larga):
            larga = cadena

    return larga

Soluciones variables

import datetime

ahora = datetime.datetime.now()

anio_actual=ahora.year
anio_actual=2025
anio_nacimiento=int(input("Dime tu año de nacimiento"))

print(f"Este año tendrás {anio_actual-anio_nacimiento} años")

# Calcular el área de un triángulo
base=float(input("Dime la base"))
altura=float(input("Dime la altura"))
area=base*altura/2
print("El área es ",area)
# saber hacer esto es importante porque puede ser que queramos
# almacenar el valor, no imprimirlo
print("El área es "+str(area))
print(f"El área es {area}")

# Pido el número
numero=int(input("Dime un numero del 10 al 99"))
decenas=numero//10
unidades=numero%10
suma=decenas+unidades
print("La suma es ",suma)

# Pido los minutos
total_minutos=int(input("Dime cuantos minutos"))

# calculo horas y minutos
horas=total_minutos//60
minutos=total_minutos%60

# muestro
print(f"{horas} horas y {minutos} minutos")



Probemos el if… y todo lo demás

Cread un script de JS que nos pida (con prompt) la edad al usuario y la altura en centímetros

Si la edad es mayor de 16 o la altura mayor de 150 que muestre un mensaje que diga ‘Puedes pasar’

¿Qué pasa si el usuario no pone ningún valor (ya sabemos como son)?