¿Por qué mi código de Pandas es tan lento? Una guía práctica para la vectorización
1. El problema del bucle: por qué tu for es lento como la melaza
¿Empezaste un script de Pandas, te fuiste por un café y al volver descubriste que sigue ejecutándose? La mayoría hemos estado ahí. Tienes un DataFrame con 100,000 filas, y todo lo que necesitas es sumar dos columnas. Un bucle for parece el enfoque obvio.
Aquí está el problema: iterar sobre un DataFrame fila por fila es una de las cosas más lentas que puedes hacer en Python. En cada iteración, Pandas tiene que desempaquetar la fila, buscar los nombres de las columnas, extraer los valores y volver a empaquetar el resultado en un Series. Multiplica eso por decenas de miles de filas.
Ahora comparemos un bucle estándar con la “forma Pandas.”
import pandas as pd
import numpy as np
import time
# Create a DataFrame with 100,000 rows
df = pd.DataFrame({
'a': np.random.rand(100000),
'b': np.random.rand(100000)
})
# Method 1: The slow for-loop
start = time.time()
result = []
for i in range(len(df)):
result.append(df.iloc[i]['a'] + df.iloc[i]['b'])
df['sum_loop'] = result
loop_time = time.time() - start
# Method 2: Vectorization
start = time.time()
df['sum_vec'] = df['a'] + df['b']
vec_time = time.time() - start
print(f"Loop time: {loop_time:.4f} seconds")
print(f"Vectorized time: {vec_time:.4f} seconds")
print(f"Speedup: {loop_time / vec_time:.1f}x")
Este script de benchmark construye un DataFrame de dos columnas con 100,000 números aleatorios de tipo float y luego suma esas columnas de dos maneras diferentes para poder medir el tiempo de cada enfoque:
np.random.rand(100000)— genera 100,000 números aleatorios de tipo float en el rango [0, 1) en una sola llamada a nivel C, no en un bucle de Python.df.iloc[i]—.ilochace acceso a filas basado en posición entera. Cada llamada construye un objeto Series completo para esa fila (etiquetas de columna + metadatos de dtype + los valores), por lo que el bucle paga un sobrecosto masivo en cada iteración.df['a'] + df['b']— este es el equivalente vectorizado. Pandas pasa los dos arreglos subyacentes de NumPy directamente a código C optimizado que realiza la suma elemento por elemento en una sola pasada. Sin construcción de Series por fila, sin bucle a nivel de Python.time.time()— un temporizador de reloj usado aquí por simplicidad. Para micro-benchmarks más rigurosos recurrirías atimeito%%timeit(ver Sección 3), perotime.time()es suficiente para revelar una brecha de ~10,000×.
La conclusión clave: el resultado de ambos métodos es idéntico, pero el mecanismo es completamente diferente. El bucle hace 100,000 pequeños viajes de ida y vuelta al intérprete de Python; la suma vectorizada hace una sola pasada grande a nivel C.
En mi máquina, el bucle toma aproximadamente 5 segundos. ¿La versión vectorizada? Aproximadamente 0.0005 segundos. Eso es 10,000x más rápido. El bucle es lento porque obliga a Python a hacer todo el trabajo. La vectorización le entrega la computación a código C altamente optimizado que se ejecuta directamente en el procesador de tu computadora.
2. Qué significa realmente la vectorización
La vectorización no es magia. En lugar de que un chef (Python) cocine un grano de arroz a la vez (una fila), consiste en vaciar toda la bolsa en una vaporera (C/NumPy) de una sola vez.
Debajo de cada Series de Pandas se encuentra un arreglo de NumPy. NumPy es una biblioteca de C diseñada para manejar grandes bloques de memoria de manera eficiente. Cuando escribes df['a'] + df['b'], Pandas no itera en un bucle, sino que le entrega a NumPy dos bloques de memoria y le dice: “Suma esto usando las instrucciones matemáticas especializadas de la CPU.”
# Let's look at the 'engine' under the hood
print(type(df['a'].values))
# Output: <class 'numpy.ndarray'>
Esta línea de código quita la capa de abstracción de Pandas para revelar el motor subyacente:
df['a']— devuelve unaSeriesde Pandas, que es una envoltura de alto nivel sobre un arreglo de NumPy, además de un índice y metadatos de tipo (dtype)..values— un atributo de Pandas que extrae el arreglo crudo de NumPy que respalda laSeries, eliminando toda la maquinaria de índices y etiquetas. (En las versiones modernas de Pandas, es posible que veas que se recomienda usar.to_numpy()en su lugar, pero.valuessigue funcionando y es extremadamente común en tutoriales.)type(...)— confirma que el tipo de objeto esnumpy.ndarray, demostrando que cada columna de Pandas finalmente se encuentra sobre un bloque contiguo de memoria administrado por C.
Por eso df['a'] + df['b'] es rápido: el operador + se despacha a la suma elemento por elemento a nivel de C de NumPy, que opera sobre esos búferes ndarray crudos sin involucrar al intérprete de Python en el bucle interno.
Esto es broadcasting. Permite que NumPy opere sobre arreglos completos sin que el intérprete de Python tenga que comprobar tipos y buscar variables para cada fila individual.
3. La jerarquía de lentitud: ¿qué operaciones son realmente rápidas?
Las funciones de Pandas no son todas iguales. No se garantiza que una función que viene incluida con la biblioteca sea rápida. Aquí está la jerarquía general de velocidad:
- Operaciones vectorizadas (Más rápido):
+,-,*,/, y métodos integrados como.sum(),.mean(), o.str.upper(). - Optimizadas con Cython (Rápido):
groupby(),sort_values(), ymerge(). - Apply (Lento):
df.apply(lambda x: ...)es esencialmente un bucle for oculto. - Iterrows/Bucles manuales (Más lento): Evita esto a menos que no tengas otra opción.
# Timing the hierarchy
# 1. Vectorized
%timeit df['a'] + df['b']
# 2. Apply (The 'Hidden' Loop)
%timeit df.apply(lambda row: row['a'] + row['b'], axis=1)
Esto usa %timeit, un comando mágico (magic command) de IPython/Jupyter que ejecuta automáticamente la expresión muchas veces y reporta el promedio más la desviación estándar — mucho más confiable que una sola instantánea de time.time():
%timeit df['a'] + df['b']— mide el tiempo de la suma vectorizada pura. Debido a que esto se delega a la capa C de NumPy, reportará tiempos en el rango de los microsegundos incluso para 100,000 filas.%timeit df.apply(lambda row: ..., axis=1)— mide el tiempo deapplyconaxis=1, lo que significa “operar fila por fila”. Pandas itera internamente y, para cada fila, construye una Serie, desempaquetarow['a']yrow['b'], llama allambdade Python y reempaqueta el resultado. Esta construcción de Series por fila es el costo oculto — ellambdaen sí es trivial, pero la maquinaria circundante no lo es.axis=1— el argumento del eje que desencadena la iteración por filas.axis=0(por columnas) a veces puede ser más económico porque evita construir una Serie por elemento, peroaxis=1es la ruta clásica del “bucle oculto”.
Verás que el tiempo de apply es a menudo cientos de veces más lento que el operador + con los mismos datos — a pesar de que ambos producen el resultado idéntico.
Clasificados por velocidad (más rápido → más lento), con orientación sobre cuándo cada uno es la opción adecuada:
| Rango | Enfoque | Velocidad | Cuándo usarlo |
|---|---|---|---|
| 🥇 1st | Operaciones vectorizadas por columnas (df['a'] + df['b'], np.select, .str.upper()) | Más rápido — despacho único a código C a nivel de NumPy/CF | Elección predeterminada para cualquier operación aritmética, comparación, método de cadenas de texto o reducción que pueda expresarse por columnas. Siempre prueba esto primero. |
| 🥈 2nd | .apply() con axis=1 (o axis=0) | 10–50× más lento que el vectorizado — un “bucle for oculto” | Cuando la lógica por elemento es genuinamente demasiado compleja para vectorizar fácilmente (p. ej., llamar a una función de una biblioteca externa, lógica de ramificación multilínea que no se asigna a np.select), y no puedes encontrar una función integrada que haga el trabajo. Aceptable para código de limpieza de datos en DataFrames de tamaño pequeño a mediano. |
| 🥉 3rd | Bucles por filas vía .iloc o iterrows() | Más lento — sobrecarga de Python por fila más construcción de Series por acceso | Casi nunca la herramienta adecuada para aritmética. Legítimo solo cuando necesitas efectos secundarios dependientes del orden de las filas (p. ej., una máquina de estados acumulativa donde cada fila depende del resultado calculado de la fila anterior), o cuando estás portando lógica de otro lenguaje línea por línea y la corrección importa más que la velocidad durante la portabilidad inicial. |
La idea clave: las opciones más lentas no son incorrectas — son flexibles. Un bucle for puede expresar cualquier lógica; una expresión vectorizada solo puede expresar lógica que se ajuste al modelo de operaciones de arreglos (arrays) de NumPy. El costo de rendimiento que pagas por .apply() y los bucles por filas es el precio de esa flexibilidad. La disciplina de ingeniería es buscar la herramienta más rápida que aún pueda expresar tu lógica correctamente, en lugar de optar por la más flexible por costumbre.
Verás que apply se ejecuta mucho más lento que el operador +. ¿Por qué? Porque apply aún llama a tu función de Python 100,000 veces.
4. Aritmética vectorizada: la victoria fácil
La forma más fácil de acelerar tu código es dejar de pensar en filas y empezar a pensar en columnas. ¿Necesitas un margen de beneficio? No recorras las filas en un bucle para calcular (revenue - cost) / revenue. Simplemente hazlo todo de una vez.
df['revenue'] = np.random.randint(100, 1000, 100000)
df['cost'] = np.random.randint(50, 500, 100000)
# Fast, vectorized calculation
df['margin'] = (df['revenue'] - df['cost']) / df['revenue']
print(df['margin'].head(3))
Este bloque demuestra el patrón de “pensar en columnas, no en filas”:
np.random.randint(100, 1000, 100000)— genera 100,000 enteros aleatorios en [100, 1000) en una sola llamada a nivel C, produciendo un array de NumPy que Pandas envuelve en una Series al asignarlo adf['revenue'].(df['revenue'] - df['cost']) / df['revenue']— una expresión vectorizada compuesta. Pandas la evalúa de izquierda a derecha en la capa C de NumPy: primero la resta produce una Series temporal, luego la división produce la Series final. Dos pases a nivel C, cero iteración de filas a nivel Python.df['margin'].head(3)—.head(3)devuelve solo las primeras tres filas de la Series resultante para una verificación rápida sin imprimir los 100,000 valores.
Ten en cuenta que tanto la resta como la división son operaciones elemento a elemento sobre Series alineadas — Pandas empareja las filas por índice automáticamente, así que incluso si las columnas tuvieran ordenamientos diferentes (no los tienen aquí, pero podrían tenerlos), la operación matemática se alinearía correctamente.
Esto funciona porque Pandas sobrecarga los operadores matemáticos. Cuando usas / entre dos Series, sabe que quieres una división fila por fila realizada en la rápida capa C.
5. Indexación y filtrado booleano: condicionales vectorizados
¿Qué pasa si solo quieres aplicar un cálculo a algunas filas? Muchas personas recurren a una sentencia if dentro de un bucle. Eso es una trampa de rendimiento. Usa Indexación Booleana en su lugar.
# The slow way: loop + if
# The fast way: Boolean Mask
mask = df['revenue'] > 500
df.loc[mask, 'status'] = 'High Value'
df.loc[~mask, 'status'] = 'Standard'
print(df['status'].value_counts())
Este bloque reemplaza un if/else dentro de un bucle con enmascaramiento booleano, el enfoque idiomático de Pandas para la lógica condicional:
df['revenue'] > 500— una comparación vectorizada. NumPy compara cada elemento del arreglorevenuecontra 500 y devuelve una Serie booleana de la misma longitud (Truedonde los ingresos superan 500,Falseen caso contrario). Esta es la “máscara”.df.loc[mask, 'status'] = 'High Value'—.loces un acceso basado en etiquetas, pero cuando su primer argumento es una Serie booleana, selecciona solo las filas donde la máscara esTruey asigna el valor a la columnastatusexactamente para esas filas. El valor escalar'High Value'se propaga a todas las filas seleccionadas.~mask— el operador NOT a nivel de bits aplicado a una Serie booleana. Invierte cadaTrueaFalsey viceversa, produciendo la máscara complementaria para las filas de “todo lo demás”..value_counts()— un método de Pandas que cuenta los valores únicos en una Serie y los devuelve ordenados por frecuencia — una forma rápida de verificar la división entreHigh ValueyStandard.
El punto crítico: la comparación > y la asignación .loc son ambas vectorizadas, por lo que toda la lógica condicional se ejecuta en C sin ninguna ramificación a nivel de Python por cada fila.
Aquí, df['revenue'] > 500 construye una “máscara” — una lista de valores True/False. Luego .loc le indica a Pandas: actualiza la columna ‘status’ solo donde la máscara es True. Tanto la comparación como la asignación están vectorizadas, por lo que esto se ejecuta casi instantáneamente.
6. Cuando apply() parece tentador (y por qué deberías resistirte)
apply() es el canto de sirena de Pandas. Parece limpio y pitónico. Suele ser una trampa, ejecutándose de 10x a 50x más lento que una alternativa vectorizada.
Lo que realmente está pasando aquí: Cuando usas axis=1, Pandas construye un nuevo objeto Series para cada fila. Pasa cada uno a tu función. Crear 100,000 objetos Series lleva tiempo.
Para lógica compleja, recurre a np.select o pd.cut en lugar de apply.
# Instead of apply with a complex function:
def categorize(val):
if val > 0.8: return 'A'
if val > 0.5: return 'B'
return 'C'
# Use np.select (Vectorized if-else)
conditions = [
(df['a'] > 0.8),
(df['a'] > 0.5)
]
choices = ['A', 'B', 'C']
df['category'] = np.select(conditions, choices, default='C')
Este bloque contrasta una función de Python con if/elif/else (que te obligaría a usar apply) con np.select, la condicional vectorizada de múltiples ramas de NumPy:
def categorize(val)— una función simple de Python con comprobacionesifen cascada. Para usar esto en una columna de un DataFrame, necesitaríasdf['a'].apply(categorize), lo cual llama a la función una vez por elemento (100,000 llamadas a funciones de Python) — la ruta lenta mostrada para contrastar.np.select(conditions, choices, default='C')— el reemplazo vectorizado. Toma una lista de arreglos booleanos (conditions) y una lista de valores correspondiente (choices), luego para cada elemento elige el primerchoices[i]cuyoconditions[i]seaTrueen esa posición. Si ninguno coincide, usadefault. Conceptualmente, esto es una cascadaif / elif / elif / elsevectorizada — pero la bifurcación ocurre en C, no en Python.(df['a'] > 0.8)y(df['a'] > 0.5)— cada una es una comparación vectorizada que produce una Series booleana.np.selectlas evalúa posicionalmente.default='C'— el valor de respaldo para las filas donde ninguna condición es verdadera (es decir,df['a'] <= 0.5).
El resultado es idéntico a llamar a categorize en cada fila, pero calculado en una sola pasada a nivel de C. La regla general: cualquier cadena de if/elif en una sola columna generalmente puede reemplazarse por np.select con una lista de condiciones.
7. Groupby: vectorización a gran escala
Agrupar datos manualmente con bucles es lento y tedioso. groupby() de Pandas está altamente optimizado. Utiliza una estrategia de “dividir-aplicar-combinar”, implementada principalmente en Cython (extensiones de C para Python).
df['group'] = np.random.choice(['North', 'South', 'East', 'West'], 100000)
# Blazing fast aggregation
grouped_stats = df.groupby('group')['revenue'].agg(['sum', 'mean', 'count'])
print(grouped_stats)
Este bloque crea una columna de agrupación categórica y luego agrega dentro de cada grupo:
np.random.choice([...], 100000)— extrae 100,000 muestras aleatorias (con reemplazo) de las cuatro etiquetas de región, produciendo un arreglo de cadenas que Pandas envuelve en una Series.df.groupby('group')— el paso de división. Pandas divide las filas del DataFrame en grupos según los valores únicos de la columnagroup. Internamente, esto utiliza tablas hash y está implementado en Cython (extensiones de Python compiladas a C), no en Python puro.['revenue']— selecciona una sola columna de cada grupo, produciendo una Series agrupada (un objetoSeriesGroupBy)..agg(['sum', 'mean', 'count'])— los pasos de aplicación + combinación en una sola llamada. Para cada grupo, Pandas calcula las tres agregaciones nombradas y luego combina los resultados por grupo en un único DataFrame indexado por etiqueta de grupo. Pasar una lista de cadenas (los nombres de las funciones de agregación) activa la ruta optimizada de Cython para cada una.
Si alguna vez te encuentras escribiendo for grp in df['group'].unique(): ..., esa es una señal de que deberías estar usando groupby en su lugar: hace el mismo trabajo pero en C compilado en lugar de Python interpretado.
Incluso con millones de filas, esta operación suele terminar en milisegundos. Por lo tanto, si te encuentras haciendo un bucle sobre df['column'].unique(), probablemente deberías usar groupby en su lugar.
8. Refactorización práctica: cómo convertir un script lento
Aquí hay un patrón lento común que vale la pena corregir. Digamos que estamos trabajando con datos de ventas.
La versión lenta:
# DO NOT DO THIS
for i, row in df.iterrows():
if row['group'] == 'North':
df.at[i, 'adjusted_rev'] = row['revenue'] * 1.1
else:
df.at[i, 'adjusted_rev'] = row['revenue']
Este es el “anti-patrón” — un bucle fila por fila que existe por contraste, para hacer concreta la aceleración en el siguiente bloque:
df.iterrows()— un generador de Pandas que produce pares(index, Series), uno por fila. Cadarowes un objeto Series recién construido, por lo que esto es lento: 100,000 filas significa 100,000 asignaciones de Series solo para leer los datos.for i, row in ...— desempaquetado estándar de tuplas en Python para cada par(index, row).df.at[i, 'adjusted_rev'] = ...—.ates un accesor escalar basado en etiquetas, usado aquí para escribir una celda a la vez dentro del bucle. Cada asignación activa la maquinaria interna de alineación de Pandas para un solo valor, lo cual es extremadamente costoso por escritura en comparación con una asignación vectorizada de columna.row['group'] == 'North'— una ramaifa nivel de Python evaluada por fila.
El bucle es correcto, pero paga el costo de “desempaquetado de fila + escritura de celda única + rama de Python” 100,000 veces por separado.
El refactor rápido:
# DO THIS INSTEAD
df['adjusted_rev'] = df['revenue']
df.loc[df['group'] == 'North', 'adjusted_rev'] *= 1.1
Este es el refactor idiomático — dos líneas vectorizadas que reemplazan todo el bucle anterior:
df['adjusted_rev'] = df['revenue']— asigna toda la columnarevenuecomo valor por defecto paraadjusted_rev. Esta es una única copia de array a nivel de C — sin iteración de filas, sin sobrecarga de Python por elemento. La nueva columna ahora existe para las 100,000 filas.df.loc[df['group'] == 'North', 'adjusted_rev']— la máscara booleanadf['group'] == 'North'es una comparación vectorizada que produce una Series de True/False..locla usa para seleccionar solo las filasNorthde la columnaadjusted_rev.*= 1.1— el operador de multiplicación in-place, aplicado vía.locsolo a las filas enmascaradas. Esta es una asignación de multiplicación vectorizada: Pandas multiplica cada elemento seleccionado por 1.1 en C sin construir Series intermedias por fila.
El patrón es “establecer un valor por defecto sensato para toda la columna, luego sobrescribir un subconjunto usando una máscara booleana”. El paso de sobrescritura es en sí mismo vectorizado, por lo que el costo total es dos pasadas a nivel de C en lugar de 100,000 iteraciones a nivel de Python.
Un bucle que tomaba segundos se convierte en dos líneas que se ejecutan en microsegundos. Primero establecemos un valor por defecto para toda la columna (vectorizado), luego actualizamos filas específicas con una máscara (también vectorizado).
9. Cuando la vectorización no es suficiente
A veces, ni siquiera Pandas vectorizado es lo suficientemente rápido. Si superas los 10 millones de filas, es probable que alcances los límites de la RAM o de la naturaleza de un solo subproceso de Pandas.
A partir de aquí, tres opciones principales:
- Polars: Una biblioteca de DataFrames más nueva escrita en Rust. Se ejecuta más rápido que Pandas y maneja el multihilo automáticamente.
- Numba: Escribe un bucle estándar de Python y luego compílalo a código máquina al vuelo con
@jit. - DuckDB: Con conjuntos de datos enormes, a veces es más rápido ejecutar una consulta SQL directamente sobre el archivo en lugar de cargarlo en un DataFrame.
10. Resumen y próximos pasos
La conclusión es simple: evita los bucles a toda costa.
- Los bucles son lentos — se ejecutan en el intérprete de Python.
- La vectorización es rápida — utiliza código C optimizado y arreglos de NumPy.
- Usa
.loccon máscaras booleanas en lugar de bloquesif-else. - Usa
groupbyen lugar de agrupar manualmente. - Resiste
apply(); busca primero una función integrada de NumPy o Pandas.
A continuación en esta serie pasamos a la Optimización de Memoria — cómo hacer que tus DataFrames ocupen 80% menos espacio, para que puedas procesar conjuntos de datos más grandes en tu laptop. ¿Quieres un punto de partida? Toma uno de tus scripts antiguos y refactorízalo hoy.
Comprueba tu comprensión
Las preguntas a continuación avanzan desde el simple recuerdo hasta el diseño abierto, siguiendo aproximadamente la Taxonomía de Bloom.
Recordar
Según la “Jerarquía de lentitud” del artículo, ¿qué rango ocupa .apply() en comparación con las operaciones vectorizadas y groupby()?
Comprender
Con tus propias palabras, explica por qué df.apply(lambda row: ..., axis=1) se denomina “bucle for oculto” a pesar de que no contiene una palabra clave for explícita.
Aplicar
Usando el patrón de “Fast Refactor” del artículo (establecer un valor de columna por defecto y luego sobrescribir filas específicas con una máscara booleana), reescribe esta lógica basada en bucles sin usar un bucle: “para las filas de la región Sur, aplica un 5% de descuento a la columna price; deja todas las demás filas sin cambios.”
Analizar
La Sección 6 del artículo explica que apply(axis=1) crea un nuevo objeto Series para cada fila antes de pasarlo a tu función. Explica paso a paso por qué esta creación de objetos por fila es costosa incluso antes de que se ejecute la lógica real de tu función: ¿qué trabajo está haciendo Pandas que una operación vectorizada con + en dos columnas omite por completo?
Evaluar
La Sección 9 del artículo enumera Polars, Numba y DuckDB como opciones cuando Pandas vectorizado no es lo suficientemente rápido. Critica el hecho de saltar directamente a una de estas herramientas como primer paso para un pipeline lento, antes de revisar las técnicas de las Secciones 1-8 del artículo: ¿cuál es el riesgo de recurrir a una nueva librería antes de confirmar que el código existente no está simplemente lleno de bucles o llamadas a apply() que se pueden evitar?
Crear
Diseña un plan de refactorización para un nuevo script lento: itera a través de un DataFrame de pedidos y, para cada fila, establece una columna shipping_tier basada en tres niveles de order_total (menos de $50 = “standard”, $50-$200 = “priority”, más de $200 = “express”). Usando el patrón np.select del artículo de la Sección 6, esboza el reemplazo vectorizado.
Artículos relacionados
- Vectorización en Python: por qué es 100–1000× más rápido — un análisis más profundo de la mecánica de la capa NumPy/C que hace que las operaciones vectorizadas sean dramáticamente más rápidas que los bucles en Python.
- Deja de escribir código Pandas desordenado: cómo el encadenamiento de métodos hace que tu código sea legible — combina la vectorización con el encadenamiento de métodos para crear pipelines que sean rápidos y legibles.
Referencias y lecturas adicionales
- Pandas — Enhancing Performance — guía oficial sobre las optimizaciones de Cython,
numbayeval()para cuando la vectorización integrada no es suficiente. - NumPy — Broadcasting — el mecanismo subyacente que permite que las operaciones vectorizadas de Pandas/NumPy funcionen en arreglos completos sin la sobrecarga por elemento de Python.
Esta traducción fue generada automáticamente y puede contener errores. Si el idioma inglés es tu preferencia, puedes leer el artículo original en inglés .
«Aplica lo que aprendiste» es para suscriptores Supporter e Insider.
Suscríbete para desbloquear los ejercicios de este artículo.
Ver planesArtículos relacionados
- Ingeniería en Python En revisión
¿Por qué falla mi pipeline de datos? Una guía amigable para el perfilado de memoria en Python
Aprende a diagnosticar y solucionar los bloqueos por MemoryError en Python en tus pipelines de datos usando memory_profiler, Fil y chunking para gestionar grandes volúmenes de datos con memoria RAM limitada.
- Ingeniería en Python En revisión
Generadores de Python: Cómo procesar conjuntos de datos masivos sin colapsar tu computadora
Aprende cómo los generadores de Python y la palabra clave yield te permiten procesar en flujo conjuntos de datos masivos con un consumo de memoria constante, evitando el MemoryError sin tener que cargar todo en la RAM.
- Ingeniería en Python En revisión
Deja de hacer sopa de variables: una guía para el encadenamiento de métodos en Pandas
Reemplaza los dataframes intermedios desordenados con cadenas de métodos limpias de Pandas usando .assign(), .pipe() y .query() para construir pipelines de datos legibles y mantenibles.
- Estadística En revisión
Pearson vs Spearman vs Kendall: Cómo elegir la correlación adecuada para tus datos
Aprende cuándo usar la correlación de Pearson, Spearman o Kendall en Python — y por qué un puntaje bajo puede significar que simplemente elegiste la herramienta incorrecta para tus datos.
¿Buscas otra cosa?
Busca en todos los artículos por título, resumen o tema.