domingo, 25 de enero de 2026

Aprendiendo Python de 0 a experto - Fundamentos para Ciencia de Datos

Data Science en Python: Una Introducción Práctica
Python // Chapter 13

Data Science in Brief

Herramientas fundamentales para análisis de datos con Python

Python se ha convertido en el lenguaje dominante en Data Science, Machine Learning e Inteligencia Artificial. Su ecosistema de bibliotecas especializadas permite a los científicos de datos realizar desde simples análisis exploratorios hasta complejos modelos predictivos con una sintaxis clara y eficiente.

En este capítulo exploraremos las herramientas fundamentales del Data Science en Python: IPython y Jupyter para desarrollo interactivo, NumPy para computación numérica, pandas para manipulación de datos, y matplotlib para visualización.

MÓDULO_01

El Ecosistema de Data Science

El ecosistema de Python para Data Science está construido sobre bibliotecas especializadas que trabajan en conjunto. Cada una resuelve un problema específico y se integra perfectamente con las demás.

Bibliotecas Fundamentales

NumPy
Arrays multidimensionales y operaciones numéricas
pandas
Manipulación y análisis de datos tabulares
matplotlib
Visualización de datos y gráficos
Jupyter
Entorno interactivo de desarrollo
Flujo de Trabajo en Data Science
Recolección
Limpieza
Análisis
Visualización
Comunicación

Instalación del Entorno

terminal
# Crear entorno virtual
$ python -m venv datascience_env
$ source datascience_env/bin/activate

# Instalar bibliotecas fundamentales
$ pip install numpy pandas matplotlib jupyter

# Iniciar Jupyter Notebook
$ jupyter notebook
Se recomienda usar conda para proyectos complejos, ya que maneja mejor las dependencias de bibliotecas científicas con componentes en C/C++.
MÓDULO_02

IPython y Jupyter Notebooks

IPython (Interactive Python) proporciona un shell interactivo mejorado con características como autocompletado, historial persistente y comandos mágicos. Jupyter Notebooks extiende esta funcionalidad a un entorno web donde puedes combinar código, texto y visualizaciones.

Características de IPython

TAB COMPLETION
Autocompletado inteligente de variables, métodos y rutas
MAGIC COMMANDS
Comandos especiales con % para tareas comunes
SHELL ACCESS
Ejecuta comandos del sistema con !

Comandos Mágicos Esenciales

ipython_magic.py
# Medir tiempo de ejecución
%timeit [x**2 for x in range(1000)]

# Ver historial de comandos
%history

# Cargar archivo externo
%load my_script.py

# Ejecutar script externo
%run my_script.py

# Ver documentación
?len

# Ver código fuente
??my_function

# Listar variables en memoria
%who
%whos  # Versión detallada

# Limpiar variables
%reset

Estructura de un Notebook

Jupyter Notebook Architecture
Celda Markdown (Documentación)
Celda Code (Python)
Output (Resultados/Gráficos)
Celda Code (Siguiente análisis)
Los Jupyter Notebooks son ideales para análisis exploratorio, prototipado rápido y comunicación de resultados. Los archivos .ipynb pueden compartirse y visualizarse en GitHub.
MÓDULO_03

NumPy: Computación Numérica

NumPy es el pilar fundamental de la computación científica en Python. Su estructura principal, el ndarray, permite operaciones vectorizadas extremadamente eficientes sobre grandes conjuntos de datos numéricos.

Creación de Arrays

numpy_basics.py
import numpy as np

# Crear arrays desde listas
arr1d = np.array([1, 2, 3, 4, 5])
arr2d = np.array([[1, 2, 3], [4, 5, 6]])

# Arrays especiales
zeros = np.zeros((3, 4))        # Matriz 3x4 de ceros
ones = np.ones((2, 3))          # Matriz 2x3 de unos
identity = np.eye(4)           # Matriz identidad 4x4
random = np.random.rand(3, 3)  # Matriz 3x3 aleatoria

# Rangos y secuencias
rango = np.arange(0, 10, 2)     # [0, 2, 4, 6, 8]
lineal = np.linspace(0, 1, 5)  # [0, 0.25, 0.5, 0.75, 1]

# Propiedades del array
print(arr2d.shape)   # (2, 3)
print(arr2d.dtype)   # int64
print(arr2d.ndim)    # 2
print(arr2d.size)    # 6

Operaciones Vectorizadas

La vectorización permite realizar operaciones sobre arrays completos sin loops explícitos, aprovechando optimizaciones en C a nivel interno.

vectorization.py
import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])

# Operaciones elemento a elemento
print(a + b)      # [11, 22, 33, 44]
print(a * b)      # [10, 40, 90, 160]
print(a ** 2)     # [1, 4, 9, 16]
print(np.sqrt(a)) # [1.0, 1.414, 1.732, 2.0]

# Funciones de agregación
print(a.sum())    # 10
print(a.mean())   # 2.5
print(a.std())    # 1.118
print(a.min())    # 1
print(a.max())    # 4

# Broadcasting: operar arrays de diferente forma
matrix = np.array([[1, 2, 3],
                   [4, 5, 6]])
print(matrix + 10)  # Suma 10 a cada elemento
python vectorization.py
[[11 12 13]
[14 15 16]]

Indexación y Slicing

slicing.py
import numpy as np

arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]])

# Indexación básica
print(arr[0, 0])      # 1 (primera fila, primera columna)
print(arr[1, 2])      # 7 (segunda fila, tercera columna)

# Slicing
print(arr[0, :])      # [1, 2, 3, 4] - primera fila completa
print(arr[:, 1])      # [2, 6, 10] - segunda columna
print(arr[:2, 1:3])  # [[2, 3], [6, 7]] - submatriz

# Indexación booleana (filtrado)
print(arr[arr > 5])   # [6, 7, 8, 9, 10, 11, 12]

# Fancy indexing
indices = [0, 2]
print(arr[indices])   # Filas 0 y 2
NumPy arrays son mutables. El slicing devuelve vistas del array original, no copias. Para obtener una copia independiente, usa arr.copy().
MÓDULO_04

pandas: Manipulación de Datos

pandas proporciona estructuras de datos de alto nivel y herramientas para el análisis de datos. Sus dos estructuras principales son Series (arrays unidimensionales con índices) y DataFrame (tablas bidimensionales etiquetadas).

Series y DataFrames

pandas_basics.py
import pandas as pd
import numpy as np

# Crear una Series
s = pd.Series([10, 20, 30, 40], 
              index=['a', 'b', 'c', 'd'])
print(s['b'])  # 20

# Crear un DataFrame desde diccionario
data = {
    'nombre': ['Ana', 'Luis', 'María', 'Carlos'],
    'edad': [25, 30, 28, 35],
    'ciudad': ['Lima', 'Bogotá', 'Lima', 'Santiago'],
    'salario': [3000, 4500, 3800, 5200]
}

df = pd.DataFrame(data)
print(df)
python pandas_basics.py
nombre edad ciudad salario
0 Ana 25 Lima 3000
1 Luis 30 Bogotá 4500
2 María 28 Lima 3800
3 Carlos 35 Santiago 5200

Selección y Filtrado

selection.py
# Seleccionar columnas
print(df['nombre'])          # Una columna (Series)
print(df[['nombre', 'edad']]) # Múltiples columnas (DataFrame)

# Seleccionar filas por índice
print(df.loc[0])              # Por etiqueta
print(df.iloc[0:2])          # Por posición (slicing)

# Filtrado condicional
mayores_28 = df[df['edad'] > 28]
print(mayores_28)

# Múltiples condiciones
filtrado = df[(df['edad'] > 25) & (df['salario'] > 4000)]
print(filtrado)

# Filtrado con isin
ciudades_interes = df[df['ciudad'].isin(['Lima', 'Bogotá'])]
print(ciudades_interes)

Operaciones de Agregación

aggregation.py
# Estadísticas descriptivas
print(df.describe())

# Agregaciones por columna
print(df['salario'].mean())   # Promedio: 4125.0
print(df['edad'].median())    # Mediana: 29.0

# GroupBy: agrupar y agregar
por_ciudad = df.groupby('ciudad')['salario'].mean()
print(por_ciudad)

# Múltiples agregaciones
resumen = df.groupby('ciudad').agg({
    'salario': ['mean', 'max'],
    'edad': 'mean'
})
print(resumen)
Resultado GroupBy
ciudad
Bogotá 4500.0
Lima 3400.0
Santiago 5200.0
Name: salario, dtype: float64

Limpieza de Datos

data_cleaning.py
import pandas as pd
import numpy as np

# DataFrame con valores faltantes
df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, np.nan, 8],
    'C': ['x', 'y', 'z', 'w']
})

# Detectar valores nulos
print(df.isnull())
print(df.isnull().sum())  # Conteo por columna

# Eliminar filas con NaN
df_limpio = df.dropna()

# Rellenar valores faltantes
df_filled = df.fillna(0)                  # Con valor fijo
df_filled = df.fillna(df.mean())          # Con promedio
df_filled = df.fillna(method='ffill')    # Forward fill

# Eliminar duplicados
df_unique = df.drop_duplicates()

# Renombrar columnas
df = df.rename(columns={'A': 'columna_a'})

# Cambiar tipos de datos
df['A'] = df['A'].astype(float)
El manejo de valores faltantes (NaN) es crucial en Data Science. pandas representa los valores faltantes con np.nan para datos numéricos y None o pd.NA para otros tipos.
MÓDULO_05

matplotlib: Visualización de Datos

matplotlib es la biblioteca de visualización más utilizada en Python. Permite crear gráficos estáticos, animados e interactivos de alta calidad, desde simples líneas hasta complejas visualizaciones científicas.

Gráficos Básicos

basic_plots.py
import matplotlib.pyplot as plt
import numpy as np

# Datos de ejemplo
x = np.linspace(0, 10, 100)
y = np.sin(x)

# Gráfico de línea
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='sin(x)', color='#00ffc8', linewidth=2)
plt.plot(x, np.cos(x), label='cos(x)', color='#ff6b9d', linewidth=2)

# Personalización
plt.title('Funciones Trigonométricas', fontsize=14)
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.grid(True, alpha=0.3)

# Guardar y mostrar
plt.savefig('trigonometric.png', dpi=150)
plt.show()

Tipos de Gráficos

Función Tipo Uso
plt.plot() Línea Series temporales, tendencias
plt.scatter() Dispersión Correlaciones, distribuciones
plt.bar() Barras Comparaciones categóricas
plt.hist() Histograma Distribución de frecuencias
plt.pie() Circular Proporciones del total
plt.boxplot() Caja Distribución y outliers

Múltiples Subplots

subplots.py
import matplotlib.pyplot as plt
import numpy as np

# Crear figura con subplots
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# Datos
x = np.linspace(0, 10, 50)
data = np.random.randn(1000)

# Subplot 1: Línea
axes[0, 0].plot(x, np.sin(x), color='#00ffc8')
axes[0, 0].set_title('Gráfico de Línea')

# Subplot 2: Dispersión
axes[0, 1].scatter(x, np.cos(x) + np.random.randn(50)*0.1, 
                   color='#ff6b9d', alpha=0.7)
axes[0, 1].set_title('Gráfico de Dispersión')

# Subplot 3: Histograma
axes[1, 0].hist(data, bins=30, color='#ffd93d', edgecolor='black')
axes[1, 0].set_title('Histograma')

# Subplot 4: Barras
categorias = ['A', 'B', 'C', 'D']
valores = [23, 45, 56, 78]
axes[1, 1].bar(categorias, valores, color='#6bcfff')
axes[1, 1].set_title('Gráfico de Barras')

plt.tight_layout()
plt.savefig('subplots.png', dpi=150)
plt.show()

Integración con pandas

pandas_plot.py
import pandas as pd
import matplotlib.pyplot as plt

# pandas integra matplotlib directamente
df = pd.DataFrame({
    'mes': ['Ene', 'Feb', 'Mar', 'Abr', 'May'],
    'ventas': [100, 150, 200, 180, 220],
    'gastos': [80, 90, 120, 110, 130]
})

# Gráfico directo desde DataFrame
df.plot(x='mes', y=['ventas', 'gastos'], 
        kind='bar', figsize=(10, 6))
plt.title('Ventas vs Gastos por Mes')
plt.ylabel('Cantidad ($)')
plt.xticks(rotation=0)
plt.legend(loc='upper left')
plt.show()
Para visualizaciones más avanzadas y estéticamente atractivas, considera usar seaborn (construido sobre matplotlib) o plotly para gráficos interactivos.
MÓDULO_06

Proyecto: Análisis de Datos Completo

Integremos todo lo aprendido en un flujo de trabajo de Data Science típico: cargar datos, limpiarlos, analizarlos y visualizar los resultados.

Carga y Exploración

project_analysis.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Cargar datos (ejemplo con CSV)
# df = pd.read_csv('datos.csv')

# Crear datos de ejemplo: ventas de productos
np.random.seed(42)
n = 200

df = pd.DataFrame({
    'fecha': pd.date_range('2024-01-01', periods=n, freq='D'),
    'producto': np.random.choice(['A', 'B', 'C'], n),
    'region': np.random.choice(['Norte', 'Sur', 'Este', 'Oeste'], n),
    'unidades': np.random.randint(10, 100, n),
    'precio': np.random.uniform(15, 50, n).round(2)
})

# Agregar valores nulos aleatorios
df.loc[np.random.choice(n, 10), 'unidades'] = np.nan

# Exploración inicial
print("="*50)
print("EXPLORACIÓN DE DATOS")
print("="*50)
print(f"\nDimensiones: {df.shape}")
print(f"\nPrimeras filas:\n{df.head()}")
print(f"\nTipos de datos:\n{df.dtypes}")
print(f"\nValores nulos:\n{df.isnull().sum()}")

Limpieza y Transformación

cleaning.py
# Manejar valores faltantes
df['unidades'] = df['unidades'].fillna(df['unidades'].median())

# Crear columnas derivadas
df['total_venta'] = df['unidades'] * df['precio']
df['mes'] = df['fecha'].dt.month
df['dia_semana'] = df['fecha'].dt.day_name()

# Categorizar precios
df['categoria_precio'] = pd.cut(
    df['precio'], 
    bins=[0, 25, 35, 50],
    labels=['Bajo', 'Medio', 'Alto']
)

print("\nDataFrame transformado:\n", df.head())

Análisis y Agregación

analysis.py
print("="*50)
print("ANÁLISIS DE DATOS")
print("="*50)

# Ventas por producto
ventas_producto = df.groupby('producto').agg({
    'total_venta': ['sum', 'mean', 'count'],
    'unidades': 'sum'
}).round(2)
print("\nVentas por Producto:\n", ventas_producto)

# Ventas por región
ventas_region = df.groupby('region')['total_venta'].sum().sort_values(ascending=False)
print("\nVentas por Región:\n", ventas_region)

# Tendencia mensual
tendencia = df.groupby('mes')['total_venta'].sum()
print("\nTendencia Mensual:\n", tendencia)

# Tabla pivote
pivot = pd.pivot_table(
    df, 
    values='total_venta', 
    index='region', 
    columns='producto', 
    aggfunc='sum'
).round(2)
print("\nTabla Pivote (Región x Producto):\n", pivot)

Visualización de Resultados

visualization.py
# Configurar estilo
plt.style.use('dark_background')

# Crear dashboard
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Dashboard de Ventas', fontsize=16, color='#00ffc8')

# 1. Ventas por producto (barras)
ventas_prod = df.groupby('producto')['total_venta'].sum()
axes[0, 0].bar(ventas_prod.index, ventas_prod.values, 
              color=['#00ffc8', '#ff6b9d', '#ffd93d'])
axes[0, 0].set_title('Ventas por Producto', color='white')
axes[0, 0].set_ylabel('Total Ventas ($)')

# 2. Distribución de precios (histograma)
axes[0, 1].hist(df['precio'], bins=20, color='#6bcfff', 
               edgecolor='white', alpha=0.8)
axes[0, 1].set_title('Distribución de Precios', color='white')
axes[0, 1].set_xlabel('Precio ($)')

# 3. Tendencia mensual (línea)
axes[1, 0].plot(tendencia.index, tendencia.values, 
               marker='o', color='#00ffc8', linewidth=2)
axes[1, 0].set_title('Tendencia Mensual', color='white')
axes[1, 0].set_xlabel('Mes')
axes[1, 0].set_ylabel('Ventas ($)')
axes[1, 0].fill_between(tendencia.index, tendencia.values, 
                        alpha=0.3, color='#00ffc8')

# 4. Ventas por región (pie)
ventas_region.plot(kind='pie', ax=axes[1, 1], 
                   colors=['#00ffc8', '#ff6b9d', '#ffd93d', '#6bcfff'],
                   autopct='%1.1f%%')
axes[1, 1].set_title('Distribución por Región', color='white')
axes[1, 1].set_ylabel('')

plt.tight_layout()
plt.savefig('dashboard_ventas.png', dpi=150, 
            facecolor='#0a0a0f', edgecolor='none')
plt.show()
Este flujo de trabajo representa el ciclo típico de Data Science: obtener datos, explorarlos, limpiarlos, analizarlos y comunicar los hallazgos mediante visualizaciones efectivas.

Resumen del Capítulo

01 // IPython & Jupyter

Entornos interactivos para desarrollo exploratorio con comandos mágicos y notebooks ejecutables.

02 // NumPy

Arrays multidimensionales eficientes con operaciones vectorizadas y broadcasting.

03 // pandas

Series y DataFrames para manipulación de datos tabulares con selección, filtrado y agregación.

04 // matplotlib

Visualización de datos con gráficos de línea, barras, dispersión, histogramas y más.

Basado en "Learn Python Programming, 4th Edition" // Fabrizio Romano & Heinrich Kruger

Chapter 13: Data Science in Brief // Packt Publishing