Considere el siguiente marco de datos:
A B C D
0 foo one 0.162003 0.087469
1 bar one -1.156319 -1.526272
2 foo two 0.833892 -1.666304
3 bar three -2.026673 -0.322057
4 foo two 0.411452 -0.954371
5 bar two 0.765878 -0.095968
6 foo one -0.654890 0.678091
7 foo three -1.789842 -1.130922
Los siguientes comandos funcionan:
> df.groupby('A').apply(lambda x: (x['C'] - x['D']))
> df.groupby('A').apply(lambda x: (x['C'] - x['D']).mean())
pero ninguno de los siguientes trabajos:
> df.groupby('A').transform(lambda x: (x['C'] - x['D']))
ValueError: could not broadcast input array from shape (5) into shape (5,3)
> df.groupby('A').transform(lambda x: (x['C'] - x['D']).mean())
TypeError: cannot concatenate a non-NDFrame object
¿Por qué? El ejemplo en la documentación parece sugerir que llamar transform
a un grupo le permite a uno realizar el procesamiento de operaciones en filas:
# Note that the following suggests row-wise operation (x.mean is the column mean)
zscore = lambda x: (x - x.mean()) / x.std()
transformed = ts.groupby(key).transform(zscore)
En otras palabras, pensé que transform es esencialmente un tipo específico de aplicación (el que no se agrega). Donde me equivoco
Como referencia, a continuación se muestra la construcción del marco de datos original anterior:
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C' : randn(8), 'D' : randn(8)})
zscore
), transform
recibe una función lambda que supone que cada uno x
es un elemento dentro del group
, y también devuelve un valor por elemento en el grupo. ¿Qué me estoy perdiendo?
apply
pasa todo el df, pero transform
pasa cada columna individualmente como una Serie. 2) apply
puede devolver cualquier salida de forma (escalar / Serie / Marco de datos / matriz / lista ...), mientras que transform
debe devolver una secuencia (Serie 1D / matriz / lista) de la misma longitud que el grupo. Es por eso que el OP apply()
no necesita transform()
. Esta es una buena pregunta ya que el documento no explicó ambas diferencias claramente. (similar a la distinción apply/map/applymap
u otras cosas ...)
transform
debe devolver un número, una fila o la misma forma que el argumento. si es un número, el número se establecerá en todos los elementos del grupo, si es una fila, se transmitirá a todas las filas del grupo. En su código, la función lambda devuelve una columna que no se puede transmitir al grupo.