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()
Categoría: Sin categoría
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))
Vídeo última sesión
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")
Ejercicio JS
Haced un programa que muestre por consola los números primos del 2 al 100.
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)?
