¡Hola a todos! Como su redactor de artículos, me emociona guiarlos a través del fascinante mundo de la manipulación y limpieza de datos. Hoy, vamos a sumergirnos en una herramienta que está revolucionando la forma en que trabajamos con grandes volúmenes de datos en Python: Polars.

Domina la Manipulación y Limpieza de Datos con Polars en Python: Potencia tu Análisis de Datos

Introducción

En el vibrante ecosistema de la ciencia de datos, la capacidad de procesar y limpiar grandes volúmenes de información de manera eficiente es más que una habilidad: es una necesidad. Durante años, Pandas ha sido el caballo de batalla para la manipulación de datos en Python, y con razón. Sin embargo, a medida que los datasets crecen en tamaño y complejidad, surgen desafíos en cuanto a rendimiento y consumo de memoria. Aquí es donde entra en juego Polars, una librería escrita en Rust que nos ofrece una alternativa increíblemente rápida y eficiente en memoria para el procesamiento de datos.

¿Por Qué Polars?

Polars no es solo otra librería de manipulación de datos. Ha sido diseñada desde cero para aprovechar al máximo la paralelización y la eficiencia computacional, lo que la convierte en una elección sobresaliente para trabajar con datasets que superan las capacidades de Pandas en términos de velocidad y memoria. Su API, aunque inspirada en Pandas, introduce un enfoque más funcional y “lazy” (evaluación diferida) que permite optimizaciones significativas.

Audiencia y Objetivos del Artículo

Este artículo está dirigido a científicos de datos, analistas y cualquier desarrollador Python que busque mejorar sus habilidades en la manipulación y limpieza de datos, especialmente cuando se enfrenta a grandes conjuntos de datos. Mi objetivo es que, al finalizar esta lectura, ustedes no solo entiendan los fundamentos de Polars, sino que también sean capaces de aplicarlo en escenarios reales para transformar datos sucios en información valiosa, lista para el análisis o la construcción de modelos de Machine Learning.

Metodología: Preparando el Terreno para Datos Limpios y Rápidos

Para demostrar el poder de Polars, he seleccionado cuidadosamente dos datasets públicos que presentan las características ideales para una sesión práctica de limpieza y manipulación: son lo suficientemente grandes para evidenciar la eficiencia de Polars y, como era de esperar en datos del mundo real, contienen esas “imperfecciones” que tanto nos gustan (valores faltantes, tipos de datos inconsistentes, etc.).

Selección de Datasets

Dataset 1: NYC Yellow Taxi Trip Data (Enero 2023)

Este dataset, proporcionado por la Comisión de Taxis y Limusinas (TLC) de la Ciudad de Nueva York, contiene millones de registros de viajes de taxis amarillos. Es ideal por su tamaño considerable y la variedad de tipos de datos, incluyendo marcas de tiempo, valores numéricos y categóricos. A menudo, presenta valores nulos en columnas como dropoff_datetime, fare_amount o tip_amount, y puede contener outliers o inconsistencias en los datos de viaje.

  • Fuente: NYC Taxi & Limousine Commission
  • Enlace de descarga directo (Enero 2023 Parquet): https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_2023-01.parquet
Dataset 2: Inside Airbnb NYC (Listings detallados)

El dataset de Airbnb para la ciudad de Nueva York nos ofrece una vista detallada de los listados de propiedades, incluyendo información sobre precios, ubicaciones, descripciones y comentarios. Es perfecto para practicar la manipulación de cadenas de texto, el manejo de múltiples variables categóricas y la imputación de valores faltantes en características como el número de reseñas, el precio o la disponibilidad.

  • Fuente: Inside Airbnb
  • Enlace de descarga directo (Mayo 2024, listings.csv.gz): http://data.insideairbnb.com/united-states/ny/new-york-city/2024-05-23/data/listings.csv.gz

Configuración del Entorno

Antes de sumergirnos en el código, es crucial tener nuestro entorno de desarrollo listo. Les recomiendo crear un entorno virtual para gestionar las dependencias de este proyecto. Aquí están las librerías principales que utilizaremos:

# requirements.txt
polars==0.20.18
matplotlib==3.8.4
seaborn==0.13.2
numpy==1.26.4
pandas==2.2.2 # Opcional, para benchmarks

Pueden instalar estas dependencias con pip:

pip install -r requirements.txt

Códigos: Manipulación y Limpieza de Datos con Polars en Acción

¡Es hora de ensuciarnos las manos con el código! A continuación, les mostraré cómo realizar las tareas más comunes de manipulación y limpieza de datos utilizando Polars, aplicando estos conceptos a nuestros datasets seleccionados.

Carga Eficiente de Datos

Polars destaca por su eficiencia al leer datos, especialmente con formatos optimizados como Parquet. Utilizaremos la función pl.read_parquet para el dataset de taxis y pl.read_csv para el de Airbnb.

import polars as pl
import pandas as pd # Para una posible comparación
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# Carga del dataset de Taxis de NYC (Parquet)
taxi_df = pl.read_parquet("https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_2023-01.parquet")
print("Dataset de Taxis cargado. Filas:", taxi_df.shape[0], "Columnas:", taxi_df.shape[1])

# Carga del dataset de Airbnb NYC (CSV comprimido)
# Usaremos Pandas para descargar y luego Polars para leer, o directamente Polars si soporta la URL gzipped.
# Polars puede leer directamente desde URLs con gzip si el content-encoding es correcto.
try:
    airbnb_df = pl.read_csv("http://data.insideairbnb.com/united-states/ny/new-york-city/2024-05-23/data/listings.csv.gz", infer_schema_length=10000, ignore_errors=True)
except Exception as e:
    print(f"Error al cargar Airbnb directamente con Polars: {e}. Intentando con Pandas para descargar...")
    # Si Polars tiene problemas con la URL gzipped, podemos usar Pandas para la descarga y luego Polars para leer el archivo local.
    # Alternativamente, podemos descargar el archivo manualmente o usar requests.
    import requests
    import gzip
    response = requests.get("http://data.insideairbnb.com/united-states/ny/new-york-city/2024-05-23/data/listings.csv.gz")
    with open("listings.csv.gz", "wb") as f:
        f.write(response.content)
    airbnb_df = pl.read_csv("listings.csv.gz", infer_schema_length=10000, ignore_errors=True)


print("Dataset de Airbnb cargado. Filas:", airbnb_df.shape[0], "Columnas:", airbnb_df.shape[1])

Exploración Inicial de Datos

Una vez cargados los datos, el primer paso es siempre explorarlos. Esto nos ayuda a entender su estructura, identificar posibles problemas y planificar nuestra estrategia de limpieza.

# Inspección de las primeras filas
print("Primeras 5 filas del dataset de Taxis:")
print(taxi_df.head())

print("\nPrimeras 5 filas del dataset de Airbnb:")
print(airbnb_df.head())

# Resumen estadístico
print("\nResumen estadístico del dataset de Taxis:")
print(taxi_df.describe())

print("\nResumen estadístico del dataset de Airbnb (columnas numéricas):")
# Seleccionamos solo columnas numéricas para el describe en Airbnb, ya que tiene muchas de texto.
numeric_cols_airbnb = airbnb_df.select(pl.col(pl.NUMERIC_DTYPES)).columns
print(airbnb_df.select(numeric_cols_airbnb).describe())

# Identificación de valores faltantes
print("\nConteo de valores nulos por columna en el dataset de Taxis:")
print(taxi_df.null_count())

print("\nConteo de valores nulos por columna en el dataset de Airbnb:")
print(airbnb_df.null_count())

# Análisis de tipos de datos
print("\nTipos de datos del dataset de Taxis:")
print(taxi_df.dtypes)

print("\nTipos de datos del dataset de Airbnb:")
print(airbnb_df.dtypes)


📊 Salida:

Primeras 5 filas del dataset de Taxis:

Filtrado y Selección de Datos

Filtrar y seleccionar datos son operaciones fundamentales. Polars hace esto de manera muy intuitiva y eficiente.

# Filtrado de filas: viajes con un 'trip_distance' mayor a 5 millas en el dataset de taxis
filtered_taxi_df = taxi_df.filter(pl.col("trip_distance") > 5)
print("\nViajes con distancia > 5 millas:", filtered_taxi_df.shape[0])

# Selección de columnas: solo 'tpep_pickup_datetime', 'trip_distance', 'fare_amount'
selected_cols_taxi_df = taxi_df.select(["tpep_pickup_datetime", "trip_distance", "fare_amount"])
print("\nColumnas seleccionadas del dataset de Taxis:")
print(selected_cols_taxi_df.head())

# Renombrar columnas: renombrar 'fare_amount' a 'monto_tarifa' en el dataset de taxis
renamed_taxi_df = taxi_df.rename({"fare_amount": "monto_tarifa"})
print("\nColumnas del dataset de Taxis con 'fare_amount' renombrado:")
print(renamed_taxi_df.columns)

# Filtrado y selección en Airbnb: apartamentos con 'price' mayor a 100 y 'room_type' == 'Entire home/apt'
filtered_airbnb_df = airbnb_df.filter(
    (pl.col("price") > 100) & (pl.col("room_type") == "Entire home/apt")
).select(["name", "neighbourhood", "price", "room_type", "number_of_reviews"])
print("\nAirbnb filtrado por precio y tipo de habitación:")
print(filtered_airbnb_df.head())

Transformación y Creación de Nuevas Columnas

Polars facilita la creación de nuevas características o la modificación de las existentes con operaciones vectorizadas.

# Taxis: Calcular la velocidad promedio (trip_distance / trip_duration)
# Primero, necesitamos convertir las columnas de fecha y hora a tipo datetime y calcular la duración.
taxi_df_transformed = taxi_df.with_columns([
    (pl.col("tpep_dropoff_datetime") - pl.col("tpep_pickup_datetime")).dt.total_seconds().alias("trip_duration_seconds")
]).with_columns([
    (pl.col("trip_distance") / (pl.col("trip_duration_seconds") / 3600)).alias("avg_speed_mph").fill_null(0) # Convertir segundos a horas y manejar divisiones por cero
])
print("\nDataset de Taxis con 'trip_duration_seconds' y 'avg_speed_mph':")
print(taxi_df_transformed.select(["trip_distance", "trip_duration_seconds", "avg_speed_mph"]).head())

# Airbnb: Crear una columna de disponibilidad anual (si existe 'availability_365')
# También, convertir 'price' a un tipo numérico si no lo es (a menudo viene como string con '$' y comas)
# Para este ejemplo, asumiremos que 'price' ya es numérico o lo limpiaremos.
# Vamos a limpiar 'price' si es string
if airbnb_df["price"].dtype == pl.String:
    airbnb_df = airbnb_df.with_columns(
        pl.col("price").str.replace_all(r"[$,]", "").cast(pl.Float64, strict=False).alias("price_numeric")
    )
    # Rellenar nulos después de la conversión si se generaron por errores de parseo
    airbnb_df = airbnb_df.with_columns(pl.col("price_numeric").fill_null(pl.col("price_numeric").median()))
else:
    airbnb_df = airbnb_df.with_columns(pl.col("price").alias("price_numeric"))


airbnb_df_transformed = airbnb_df.with_columns(
    (pl.col("availability_365") > 0).alias("is_available_any_time")
)
print("\nDataset de Airbnb con 'price_numeric' (limpio) y 'is_available_any_time':")
print(airbnb_df_transformed.select(["price", "price_numeric", "availability_365", "is_available_any_time"]).head())

Agregación de Datos con GroupBy

Las operaciones de groupby son esenciales para el análisis. Polars las ejecuta con una velocidad impresionante.

# Taxis: Tarifa promedio por método de pago
avg_fare_by_payment = taxi_df_transformed.group_by("payment_type").agg(
    pl.col("fare_amount").mean().alias("avg_fare_amount"),
    pl.col("trip_distance").sum().alias("total_distance")
)
print("\nTarifa promedio y distancia total por tipo de pago en Taxis:")
print(avg_fare_by_payment)

# Airbnb: Precio promedio y número total de reseñas por tipo de habitación y barrio
avg_price_by_room_type_and_neighborhood = airbnb_df_transformed.group_by(["room_type", "neighbourhood"]).agg(
    pl.col("price_numeric").mean().alias("avg_price"),
    pl.col("number_of_reviews").sum().alias("total_reviews")
).sort("avg_price", descending=True)
print("\nPrecio promedio y total de reseñas por tipo de habitación y barrio en Airbnb (top 5):")
print(avg_price_by_room_type_and_neighborhood.head())

Manejo de Valores Faltantes

Los valores faltantes son comunes en los datos reales. Polars nos ofrece métodos eficientes para identificarlos y tratarlos.

# Identificación detallada de Nulos en Taxis
print("\nValores nulos por columna en el dataset de Taxis antes de limpiar:")
print(taxi_df.null_count())

# Eliminación de filas con nulos en columnas críticas (ej. 'passenger_count')
cleaned_taxi_df_drop = taxi_df.drop_nulls(subset=["passenger_count", "trip_distance", "fare_amount"])
print("\nDataset de Taxis después de eliminar nulos en columnas clave:", cleaned_taxi_df_drop.shape[0])

# Imputación de valores faltantes en 'tip_amount' con la mediana
median_tip = cleaned_taxi_df_drop["tip_amount"].median()
cleaned_taxi_df_imputed = cleaned_taxi_df_drop.with_columns(
    pl.col("tip_amount").fill_null(median_tip)
)
print("\nConteo de nulos en 'tip_amount' después de imputar (Taxis):", cleaned_taxi_df_imputed["tip_amount"].null_count())

# Identificación detallada de Nulos en Airbnb
print("\nValores nulos por columna en el dataset de Airbnb antes de limpiar:")
print(airbnb_df.null_count())

# Imputación de 'beds' y 'bathrooms' con la moda
# Calculamos la moda de 'beds' y 'bathrooms'
mode_beds = airbnb_df["beds"].mode()[0] if airbnb_df["beds"].null_count() > 0 else None
mode_bathrooms = airbnb_df["bathrooms"].mode()[0] if airbnb_df["bathrooms"].null_count() > 0 else None

# Rellenamos los nulos
if mode_beds is not None:
    airbnb_df_imputed = airbnb_df.with_columns(
        pl.col("beds").fill_null(mode_beds)
    )
else:
    airbnb_df_imputed = airbnb_df # No hay nulos o no hay modo para imputar

if mode_bathrooms is not None:
    airbnb_df_imputed = airbnb_df_imputed.with_columns(
        pl.col("bathrooms").fill_null(mode_bathrooms)
    )
print("\nConteo de nulos en 'beds' y 'bathrooms' después de imputar (Airbnb):", 
      airbnb_df_imputed["beds"].null_count(), 
      airbnb_df_imputed["bathrooms"].null_count())

# Rellenar nulos en 'name' y 'description' con "No Disponible"
airbnb_df_imputed = airbnb_df_imputed.with_columns([
    pl.col("name").fill_null("No Disponible"),
    pl.col("description").fill_null("No Disponible")
])
print("\nConteo de nulos en 'name' y 'description' después de imputar (Airbnb):", 
      airbnb_df_imputed["name"].null_count(), 
      airbnb_df_imputed["description"].null_count())


📊 Salida:

Valores nulos por columna en el dataset de Taxis antes de limpiar:

Preparación de Datos para Machine Learning

Aunque Polars no es una librería de Machine Learning, es excelente para la etapa de preprocesamiento, dejando los datos listos para librerías como Scikit-learn.

# Codificación de variables categóricas (Label Encoding para 'payment_type' en Taxis)
# Usaremos un mapa manual simple para este ejemplo, pero en un caso real se usaría algo más robusto.
payment_type_map = {1: "Credit Card", 2: "Cash", 3: "No Charge", 4: "Dispute", 5: "Unknown", 6: "Voided trip"}
cleaned_taxi_df_imputed = cleaned_taxi_df_imputed.with_columns(
    pl.col("payment_type").map_dict(payment_type_map).alias("payment_type_name")
)
# Luego podemos convertir a tipo Categórico de Polars para optimización si es necesario
cleaned_taxi_df_imputed = cleaned_taxi_df_imputed.with_columns(
    pl.col("payment_type_name").cast(pl.Categorical)
)
print("\nDataset de Taxis con 'payment_type_name' codificado:")
print(cleaned_taxi_df_imputed.select(["payment_type", "payment_type_name"]).head())

# One-Hot Encoding para 'room_type' en Airbnb
# Polars tiene un método get_dummies similar a Pandas
one_hot_room_type = airbnb_df_imputed["room_type"].to_dummies()
airbnb_df_ml_prep = pl.concat([airbnb_df_imputed, one_hot_room_type], how="horizontal")
print("\nDataset de Airbnb con One-Hot Encoding para 'room_type' (primeras columnas):")
print(airbnb_df_ml_prep.select(["room_type", "Entire home/apt", "Private room", "Shared room"]).head())

# Selección de características numéricas para un modelo hipotético de ML
# Eliminando columnas con alta cardinalidad o texto libre por simplicidad
features_for_ml = airbnb_df_ml_prep.select(
    pl.col(pl.NUMERIC_DTYPES).exclude(["id", "host_id"]) # Excluimos IDs
).drop_nulls() # Eliminamos cualquier fila restante con nulos para el modelo

print("\nCaracterísticas numéricas preparadas para ML (Airbnb):")
print(features_for_ml.head())
print("\nShape de las características para ML:", features_for_ml.shape)

Visualizaciones Clave

Las visualizaciones nos permiten entender el impacto de nuestra limpieza y manipulación. Veamos algunos ejemplos usando Matplotlib y Seaborn, que trabajan bien con la conversión a Pandas si es necesario, o directamente con las columnas de Polars.

# Configuración para las visualizaciones
sns.set_style("whitegrid")
plt.figure(figsize=(14, 6))

# Visualización 1: Distribución de 'trip_distance' antes y después de la limpieza (Taxis)
# Convertir a Pandas para Seaborn si es necesario (o usar Plotly/Altair que tienen mejor integración con Polars)
plt.subplot(1, 2, 1)
sns.histplot(taxi_df["trip_distance"].to_numpy(), bins=50, kde=True, color='skyblue')
plt.title('Distribución de Trip Distance (Inicial)')
plt.xlabel('Distancia del Viaje (millas)')
plt.ylabel('Frecuencia')

plt.subplot(1, 2, 2)
# Suponiendo que hemos limpiado 'trip_distance' eliminando valores atípicos o nulos
# Para fines de demostración, usaremos cleaned_taxi_df_drop y filtraremos por un rango razonable
cleaned_trip_distance = cleaned_taxi_df_drop.filter(pl.col("trip_distance").is_between(0.1, 50))["trip_distance"].to_numpy()
sns.histplot(cleaned_trip_distance, bins=50, kde=True, color='lightcoral')
plt.title('Distribución de Trip Distance (Después de Limpieza/Filtrado)')
plt.xlabel('Distancia del Viaje (millas)')
plt.ylabel('Frecuencia')
plt.tight_layout()
plt.show()

# Visualización 2: Conteo de valores nulos en columnas clave de Airbnb antes y después de la imputación
null_counts_before = airbnb_df.null_count().transpose(include_header=True, column_names=["column", "null_count"])
null_counts_before = null_counts_before.filter(pl.col("null_count") > 0).sort("null_count", descending=True).head(10)

null_counts_after = airbnb_df_imputed.null_count().transpose(include_header=True, column_names=["column", "null_count"])
null_counts_after = null_counts_after.filter(pl.col("null_count") > 0).sort("null_count", descending=True).head(10)

plt.figure(figsize=(16, 6))
plt.subplot(1, 2, 1)
sns.barplot(x=null_counts_before["null_count"].to_numpy(), y=null_counts_before["column"].to_numpy(), palette='viridis')
plt.title('Top 10 Columnas con Nulos (Airbnb - Antes de Imputación)')
plt.xlabel('Conteo de Nulos')
plt.ylabel('Columna')

plt.subplot(1, 2, 2)
sns.barplot(x=null_counts_after["null_count"].to_numpy(), y=null_counts_after["column"].to_numpy(), palette='magma')
plt.title('Top 10 Columnas con Nulos (Airbnb - Después de Imputación)')
plt.xlabel('Conteo de Nulos')
plt.ylabel('Columna')
plt.tight_layout()
plt.show()

# Visualización 3: Relación entre 'price_numeric' y 'number_of_reviews' en Airbnb
plt.figure(figsize=(10, 7))
sns.scatterplot(x=airbnb_df_imputed["price_numeric"].filter(pl.col("price_numeric") < 1000).to_numpy(), 
                y=airbnb_df_imputed["number_of_reviews"].filter(pl.col("price_numeric") < 1000).to_numpy(), 
                alpha=0.5, color='green')
plt.title('Precio vs. Número de Reseñas (Airbnb, precios < 1000)')
plt.xlabel('Precio')
plt.ylabel('Número de Reseñas')
plt.show()

Benchmarks de Rendimiento (Opcional/Avanzado)

Aunque el enfoque principal de este artículo es la manipulación y limpieza, sería un desperdicio no mencionar una de las mayores ventajas de Polars: su rendimiento. Para tareas intensivas en datos, Polars a menudo supera a Pandas.

import time

# Crearemos un DataFrame grande de Pandas para la comparación
# Usaremos un subconjunto del dataset de Taxis para que la comparación sea manejable y representativa.
sample_size = 1000000 # Un millón de filas para la comparación

print(f"\nRealizando benchmarks con {sample_size} filas...")

# Convertir el DataFrame de Polars a Pandas para el benchmark
taxi_pd_df = taxi_df.sample(sample_size, seed=42).to_pandas()
taxi_pl_df = taxi_df.sample(sample_size, seed=42)

# Benchmark: Filtrado
start_time = time.time()
filtered_pd = taxi_pd_df[taxi_pd_df["trip_distance"] > 5]
end_time = time.time()
print(f"Pandas - Filtrado: {end_time - start_time:.4f} segundos")

start_time = time.time()
filtered_pl = taxi_pl_df.filter(pl.col("trip_distance") > 5)
end_time = time.time()
print(f"Polars - Filtrado: {end_time - start_time:.4f} segundos")

# Benchmark: GroupBy y agregación (media de 'fare_amount' por 'payment_type')
start_time = time.time()
groupby_pd = taxi_pd_df.groupby("payment_type")["fare_amount"].mean()
end_time = time.time()
print(f"Pandas - GroupBy: {end_time - start_time:.4f} segundos")

start_time = time.time()
groupby_pl = taxi_pl_df.group_by("payment_type").agg(pl.col("fare_amount").mean())
end_time = time.time()
print(f"Polars - GroupBy: {end_time - start_time:.4f} segundos")

# Benchmark: Creación de nueva columna ('total_amount' = 'fare_amount' + 'tip_amount')
start_time = time.time()
taxi_pd_df['total_amount'] = taxi_pd_df['fare_amount'] + taxi_pd_df['tip_amount']
end_time = time.time()
print(f"Pandas - Creación de columna: {end_time - start_time:.4f} segundos")

start_time = time.time()
taxi_pl_df = taxi_pl_df.with_columns((pl.col("fare_amount") + pl.col("tip_amount")).alias("total_amount"))
end_time = time.time()
print(f"Polars - Creación de columna: {end_time - start_time:.4f} segundos")


📊 Salida:

Realizando benchmarks con 1000000 filas...


Como pueden observar en los benchmarks, Polars consistentemente ofrece un rendimiento superior, especialmente notable en operaciones de filtrado y agrupamiento en datasets de gran tamaño. Esto se debe a su arquitectura optimizada y su capacidad para procesar datos en paralelo.

Conclusiones: Polars como tu Aliado en el Análisis de Datos

Hemos recorrido un camino completo, desde la carga inicial de datos hasta su preparación para modelos de Machine Learning, todo ello potenciado por Polars. Hemos visto cómo esta librería nos permite manejar grandes volúmenes de datos con una eficiencia asombrosa, optimizando tanto la velocidad de procesamiento como el uso de memoria.

Los principales beneficios de Polars radican en su:

  • Velocidad inigualable: Gracias a su implementación en Rust y su diseño para la paralelización.
  • Eficiencia de memoria: Manejando datasets que otras librerías podrían tener dificultades en memoria RAM.
  • API expresiva e intuitiva: Que facilita la transición desde otras librerías y permite operaciones complejas con código conciso.
  • Evaluación diferida (Lazy Evaluation): Optimizando las cadenas de operaciones para un rendimiento óptimo.

Al dominar Polars, no solo están aprendiendo una nueva herramienta; están adquiriendo la capacidad de abordar desafíos de datos que antes parecían inmanejables, abriendo nuevas puertas en sus proyectos de ciencia de datos.

Recursos Adicionales y Próximos Pasos

Si están emocionados por lo que Polars puede hacer y desean profundizar aún más, les recomiendo explorar los siguientes recursos:

  • Documentación Oficial de Polars: La mejor fuente para entender cada función y característica.
  • Repositorio de Polars en GitHub: Para mantenerse al tanto de los últimos desarrollos y contribuir a la comunidad.
  • Comunidad de Polars: Únanse a los foros y canales de Discord para interactuar con otros usuarios y desarrolladores.

Los animo a experimentar con Polars en sus propios proyectos. ¡La mejor manera de aprender es haciendo! Descarguen datasets grandes, apliquen las técnicas que hemos visto y descubran por sí mismos el impacto que Polars puede tener en su flujo de trabajo de análisis de datos.

Y recuerden, en este emocionante viaje del aprendizaje:

recuerda que siempre siempre vas a aprender un bit a la vez!


🤖 Automatiza tu trading en 5 días con Python

Únete a mi Mini-Curso gratuito por email. Aprende a extraer datos reales, crear indicadores cuantitativos y hacer backtesting profesional.