Series
o DataFrame
s (II)¶En el vídeo anterior vimos cómo aplicar funciones universales de numpy
o los métodos de pandas
a DataFrame
s. Pero puede ser que queramos aplicar nuestras propias funciones.
# Preliminares
import pandas as pd
import numpy as np
Al igual que en el vídeo anterior, para ilustrar, generamos un DataFrame
usando un generador de números aleatorios.
# Usamos el generador por defecto del módulo random de numpy
rng = np.random.default_rng()
#
df = pd.DataFrame(
rng.standard_normal(size=10).reshape(5, 2),
columns=list('xy')
)
df
x | y | |
---|---|---|
0 | -0.131601 | -0.186435 |
1 | -1.908522 | 0.039505 |
2 | 0.324792 | 1.964660 |
3 | 0.093982 | 0.760966 |
4 | 1.246065 | -0.346505 |
Empezamos por crear una función
def mi_funcion(x):
return 'es positivo' if x >= 0 else 'es negativo'
# hemos usado la construcción if else
Para aplicar nuestra función a cada elemento del DataFrame
usamos applymap
df.applymap(mi_funcion)
x | y | |
---|---|---|
0 | es negativo | es negativo |
1 | es negativo | es positivo |
2 | es positivo | es positivo |
3 | es positivo | es positivo |
4 | es positivo | es negativo |
Si quisieramos aplicar nuestra función a cada elemento de una Serie
usaríamos apply
:
df['x'].apply(mi_funcion)
0 es negativo 1 es negativo 2 es positivo 3 es positivo 4 es positivo Name: x, dtype: object
Es muy útil tener la posibilidad de definir sobre la marcha una función sin darle un nombre y usarla como argumento de un método. Se hace con lambda
.
# Para obtener el doble de cada elemento
df.applymap(lambda x: x * 2)
x -0.375284 y 2.232192 dtype: float64
apply
para un DataFrame
¶El método apply
si se aplica a un DataFrame
debe tener como argumento a una función que se aplica a toda una columna o toda una fila, no a un elemento individual.
# Ejemplo con una función que se aplica a un vector: calculamos el número de valores positivos por columna
df.apply(lambda x: (x >= 0).sum())
x 3 y 3 dtype: int64
El método apply
admite también el argumento axis=1
, para que se aplique la función fila por fila.
df.apply(lambda x: (x >= 0).sum(), axis=1)
0 0 1 1 2 2 3 2 4 1 dtype: int64
Es muy recomendable evitar
apply
si es posible, y usar las funciones denumpy
o los métodos depandas
que son muy optimizados y llevan a cabo la iteración en C.apply
lleva a cabo la iteración en Python.
En el caso anterior, podríamos por ejemplo haber obtenido el mismo resultado usando directamente el método sum
en pandas
.
(df >= 0).sum()
x 3 y 3 dtype: int64
# Fila por fila:
(df >= 0).sum(axis=1)
0 0 1 1 2 2 3 2 4 1 dtype: int64