Pandas: Aplicar una función a las filas o columnas de un DataFrame

Publicado el 28 junio 2021 por Daniel Rodríguez @analyticslane

En el caso de que necesitemos aplicar una misma función a las filas o columnas de un objeto DataFrame de Pandas contamos con el método apply(). Con el que es posible aplicar patrones de programación funcional a los conjuntos de datos. Esto hace que sea un método interesante de conocer y, cuando se comprende bien su funcionamiento, permite realizar operaciones complejas de forma eficiente. Por eso en esta entrada vamos a ver cómo aplicar una función a las filas o columnas de un DataFrame con apply().

El método apply() de los DataFrames

La biblioteca Pandas de Python proporciona un método para la clase Dataframe el cual aplica una función a lo largo un eje del Dataframe, esto es, a lo largo de cada fila o columna. Método que básicamente tiene la siguiente forma

df.apply(func, axis=0, args=())

en donde df indica un objeto DataFrame y los parámetros son

  • func: Función que se aplicará a cada columna o fila. La cual debe aceptar una serie y devuelve una serie.
  • axis: Eje a lo largo del cual se aplica la función en el conjunto de datos. Al seleccionarse el valor 0, valor que está por defecto, la función se aplica a las columnas, mientras que si se selecciona 1 se aplicará a las filas.
  • args: Argumentos adicionales para la función.

Uso básico de apply()

Antes de continuar es necesario crear un DataFrame para poder usar el método apply(). Para esto una buena opción puede ser emplear el generador de números aleatorios de NumPy. Por ejemplo, con el siguiente código se puede crear un DataFrame con tres filas y cuatro columnas.

import numpy as np
import pandas as pd

np.random.seed(0)

df = pd.DataFrame(np.random.randint(0, 100,
                                    size=(3, 4)),
                  columns=list('ABCD'))
    A   B   C   D
0  44  47  64  67
1  67   9  83  21
2  36  87  70  88

Ahora se puede aplicar el método apply() a este DataFrame, para lo que se puede usar una función lambda. Así, se puede sumar a cada uno de los elementos del conjunto de datos el valor 2.

df.apply(lambda x : x + 2)
    A   B   C   D
0  46  49  66  69
1  69  11  85  23
2  38  89  72  90

Lo que se puede hacer también mediante la definición de una función, para lo que se puede crear una función que sume 3 a cada uno de los elementos y aplicarla al conjunto de datos.

def add_3(x):
    return x + 3

df.apply(add_3)
    A   B   C   D
0  47  50  67  70
1  70  12  86  24
2  39  90  73  91

Una cosa interesante y de gran utilidad es la posibilidad de pasar a la función parámetros adicionales. Parámetros que se indican mediante la propiedad args del método, pudiéndose aplicar tanto a funciones normales como a lambda. Gracias a esto se puede crear una función genérica con la que se puede sumar cualquier valor al conjunto de datos simplemente pasando el valor como un parámetro adicional. Algo que se muestra en el siguiente ejemplo.

def add_data(x, y):
    return x + y

df.apply(add_data, args=[5])
    A   B   C   D
0  49  52  69  72
1  72  14  88  26
2  41  92  75  93

Aplicar una función a las fila o columna

Hasta ahora hemos empleado ejemplos de funciones que modifican los valores de todos los elementos de la serie por igual. Por lo que no es posible apreciar diferencias al cambiar el valor del parámetro axis. Pero, en el caso de aplicar una función que modifique cada uno de los elementos de la serie de forma diferente se podrá ver el efecto de modificar este parámetro. Un ejemplo básico es sumar un valor diferente a cada elemento de la serie.

def add_serie(x):
    return x + np.arange(len(x))

df.apply(add_serie)
    A   B   C   D
0  44  47  64  67
1  68  10  84  22
2  38  89  72  90

Ahora, al cambiar el valor de axis nos encontraremos con un resultado diferente.

df.apply(add_serie, axis=1)
    A   B   C   D
0  44  48  66  70
1  67  10  85  24
2  36  88  72  91

Observando que en el primer caso se ha aplicado las funciones por columnas, mientras que en el segundo por filas. Esto es, en el primer ejemplo se mantienen intactos los valores de la primera fila, mientras que a los de la segunda se le añade 1 y a los de la tercera dos. Mientras que en el segundo ejemplo se añade el mismo valor a cada una de las columnas.

Algo que se puede apreciar visualmente imprimiendo dentro de una función en valor de entrada.

def print_serie(x):
    print(x)
    return x

df.apply(print_serie)
0    44
1    67
2    36
Name: A, dtype: int64
0    44
1    67
2    36
Name: A, dtype: int64
0    47
1     9
2    87
Name: B, dtype: int64
0    64
1    83
2    70
Name: C, dtype: int64
0    67
1    21
2    88
Name: D, dtype: int64

Resumiendo datos con la función el método apply()

Con lo visto en el apartado anterior podemos ver que este método también se puede emplear para resumir el valor de los conjuntos de datos. Usando para ello funciones que devuelven un valor a partir de una serie, como puede ser la suma, la media, la desviación estándar, etc. Así es posible obtener el valor medio de los elementos de cada una de las columnas pasando como parámetro la función np.mean

df.apply(np.mean)
A    49.000000
B    47.666667
C    72.333333
D    58.666667

Nótese que el parámetro del método es la función, no una llamada a la misma (no se ha usado paréntesis). Esto es así porque el método apply() es el que tiene que llamar a la función.

Conclusiones

En esta ocasión se ha visto el funcionamiento del método apply() y como se puede emplear este para aplicar una función a las filas o columnas de un DataFrame. Creo que este es un método muy útil con el que se puede hacer de una forma rápida operaciones que de otra forma serían complejas. Gracias a que facilita emplear el paradigma de programación funcional, el cual es muy efectivo para el tratamiento de datos.