Transform en pandas
julio 05, 2020
Transform es método del objeto dataframe de pandas que permite aplicar funciones sobre filas o columnas, tal como un apply, o sobre secciones de dataframe (grupos) y agregar los resultados en el dataframe original, por lo que representa una opción muy poderosa además de los métodos
aggregate
, filter
y apply
.
Creado: Julio 5 de 2020
Testeado en:
Testeado en:
- Python 3.6.4
- pandas 0.24.2
In [1]:
import pandas as pd
import numpy as np
datos¶
Se crea un dataframe de ejemplo con la lista de compras de los clientes, el valor de la compra y el número de artículos llevados en esta
In [2]:
datos = {
'nombre': ['Carlos', 'María', 'Carlos', 'María', 'María', 'Miguel', 'Miguel', 'Miguel'],
'compra': [10000, 23000, 32000, 43000, 12000, 45000, 43000, 12000],
'num_articulos': [2, 3, 1, 4, 3, 2, 4, 2]
}
df = pd.DataFrame(datos)
df
Out[2]:
transform vs apply¶
El transform puede aplicar funciones sobre las columnas como un
apply
In [3]:
df['num_articulos'].transform(func=['sqrt', 'exp'])
Out[3]:
De igual manera se puede obtener este resultado usando
apply
In [4]:
df['num_articulos'].apply(['sqrt', 'exp'])
Out[4]:
Para este uso no representa una diferencia relevante en tiempo de ejecución respecto al
apply
In [5]:
%%timeit
df['num_articulos'].transform(func=['sqrt', 'exp'])
In [6]:
%%timeit
df['num_articulos'].apply(['sqrt', 'exp'])
Pero al realizar una prueba con un dataframe de 10 millones de registros se observa que el apply se ejecuta mas rápido
In [7]:
df_long = pd.DataFrame(np.random.randint(0, 100, size=(10000000, 4)), columns=list('ABCD'))
In [8]:
%%timeit
df_long['A'].transform(func=['sqrt', 'exp'])
In [9]:
%%timeit
df_long['A'].apply(['sqrt', 'exp'])
Transform posterior a un groupby¶
El uso mas interesante del
Tomando el dataframe
transform
es precisamente aplicar funciones sobre los grupos generados por un groupby
y agregar la información resultante en el dataframe original, a diferencia de los métodos aggregate
, filter
y apply
que generan un dataframe diferente en donde cada fila proviene de cada uno de los grupos formados.Tomando el dataframe
In [10]:
df
Out[10]:
Por ejemplo si tomamos este dataframe y agrupamos los datos por el nombre del cliente y estimamos el total de la compra con un
aggregation
se genera un nuevo dataframe con tres filas, los nombres de los clientes: Carlos, María y Miguel.
In [11]:
df.groupby('nombre').agg({'compra': sum})
Out[11]:
Por otro lado, al usar
transform
se le agrega la columna compra_total
con los valores con el total comprado por cada persona al dataframe original. Por ejemplo Carlos realizó 2 compras por un valor total de $10000+320000 = 42000$, por lo que cada fila en donde en la columna nombre esté Carlos tendrá el valor de $42000$ en la columna total_compra.
In [12]:
%time df['total_compra'] = df.groupby('nombre')['compra'].transform(sum)
df
Out[12]:
Esta operación se puede realizar sin usar el
transform
, por ejemplo:
In [13]:
%time total_compra = df.groupby('nombre')['compra'].sum().rename('total_compra_merge').reset_index()
%time df_1 = df.merge(total_compra)
df_1
Out[13]:
Otra forma usando
agg
In [14]:
%time total_compra = df.groupby('nombre').agg({'compra': sum}).rename(columns={'compra':'total_compra'})
%time df_1 = df.merge(total_compra.reset_index())
df_1
Out[14]:
El
Otro ejemplo para calcular esta vez los porcentajes de cada compra para cada persona:
transform
permite realizar las estimaciones de forma mas limpia.Otro ejemplo para calcular esta vez los porcentajes de cada compra para cada persona:
In [15]:
total_compra = df.groupby('nombre')['compra'].transform(sum)
df['porcentaje'] = df['compra']/total_compra * 100
df
Out[15]:
Filtrar las compras de los usuarios con compras superiores a 80000 en total
In [16]:
df[df.groupby('nombre')['compra'].transform(sum) <= 80000]
Out[16]:
In [ ]:
0 comments