python - ¿Por qué funciona df.apply(tuple) pero no df.apply(list)?
pandas dataframe (1)
Aquí hay un marco de datos:
A B C
0 6 2 -5
1 2 5 2
2 10 3 1
3 -5 2 8
4 3 6 2
Podría recuperar una columna que es básicamente una tupla de columnas del
df
original usando
df.apply
:
out = df.apply(tuple, 1)
print(out)
0 (6, 2, -5)
1 (2, 5, 2)
2 (10, 3, 1)
3 (-5, 2, 8)
4 (3, 6, 2)
dtype: object
Pero si quiero una lista de valores en lugar de una tupla de ellos, no puedo hacerlo, porque no me da lo que espero:
out = df.apply(list, 1)
print(out)
A B C
0 6 2 -5
1 2 5 2
2 10 3 1
3 -5 2 8
4 3 6 2
En cambio, necesito hacer:
out = pd.Series(df.values.tolist())
print(out)
0 [6, 2, -5]
1 [2, 5, 2]
2 [10, 3, 1]
3 [-5, 2, 8]
4 [3, 6, 2]
dtype: object
¿Por qué no puedo usar
df.apply(list, 1)
para obtener lo que quiero?
Apéndice
Momentos de algunas posibles soluciones:
df_test = pd.concat([df] * 10000, 0)
%timeit pd.Series(df.values.tolist()) # original workaround
10000 loops, best of 3: 161 µs per loop
%timeit df.apply(tuple, 1).apply(list, 1) # proposed by Alexander
1000 loops, best of 3: 615 µs per loop
El culpable está
here
.
Con
func=tuple
funciona, pero el uso de
func=list
genera una excepción desde el módulo compilado
lib.reduce
:
ValueError: (''function does not reduce'', 0)
Como puede ver, atrapan la excepción pero no se molestan en manejarla.
Incluso sin la cláusula demasiado amplia, excepto, eso es un error en los pandas . Puede intentar subirlo a su rastreador, pero se han cerrado problemas similares con cierto sabor de wont-fix o dupe.
16321: comportamiento extraño usando la lista de creación apply () basada en las columnas actuales
15628: Dataframe.apply no siempre devuelve una Serie cuando reduce = True
Este último problema se cerró, luego se volvió a abrir y se convirtió en una solicitud de mejora de documentos hace algunos meses, y ahora parece estar siendo utilizado como un vertedero para cualquier problema relacionado.
Presumiblemente no es una alta prioridad porque, como comentó piRSquared (y uno de los mantenedores de pandas comentó lo mismo ), es mejor que comprenda la lista:
pd.Series([list(x) for x in df.itertuples(index=False)])
Por lo general,
apply
sería usar un
ufunc numpy
o similar.