Desprecia tu uso de values
y as_matrix()
!
pandas v0.24.0 introdujo dos nuevos métodos para obtener matrices NumPy de objetos pandas:
to_numpy()
, que se define en Index
, Series,
y DataFrame
objetos, y
array
, Que se define en Index
y Series
objetos solamente.
Si visita los documentos de v0.24 para .values
, verá una gran advertencia roja que dice:
Advertencia: Recomendamos usar en su DataFrame.to_numpy()
lugar.
Consulte esta sección de las notas de la versión v0.24.0 y esta respuesta para obtener más información.
Hacia una mejor consistencia: to_numpy()
En el espíritu de una mejor consistencia en toda la API, to_numpy
se ha introducido un nuevo método para extraer la matriz subyacente NumPy de DataFrames.
# Setup.
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['a', 'b', 'c'])
df.to_numpy()
array([[1, 4],
[2, 5],
[3, 6]])
Como se mencionó anteriormente, este método también se define en Index
y Series
objetos (ver aquí ).
df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
De forma predeterminada, se devuelve una vista, por lo que cualquier modificación realizada afectará al original.
v = df.to_numpy()
v[0, 0] = -1
df
A B
a -1 4
b 2 5
c 3 6
Si necesita una copia, use to_numpy(copy=True
).
pandas> = 1.0 actualización para ExtensionTypes
Si está usando pandas 1.x, es probable que esté lidiando con tipos de extensión mucho más. Deberá tener un poco más de cuidado para que estos tipos de extensión se conviertan correctamente.
a = pd.array([1, 2, None], dtype="Int64")
a
<IntegerArray>
[1, 2, <NA>]
Length: 3, dtype: Int64
# Wrong
a.to_numpy()
# array([1, 2, <NA>], dtype=object) # yuck, objects
# Right
a.to_numpy(dtype='float', na_value=np.nan)
# array([ 1., 2., nan])
Esto se llama en los documentos .
Si necesitas el dtypes
...
Como se muestra en otra respuesta, DataFrame.to_records
es una buena manera de hacer esto.
df.to_records()
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
Esto no se puede hacer to_numpy
, desafortunadamente. Sin embargo, como alternativa, puede usar np.rec.fromrecords
:
v = df.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', '<U1'), ('A', '<i8'), ('B', '<i8')])
En cuanto al rendimiento, es casi lo mismo (en realidad, el uso rec.fromrecords
es un poco más rápido).
df2 = pd.concat([df] * 10000)
%timeit df2.to_records()
%%timeit
v = df2.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
11.1 ms ± 557 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
9.67 ms ± 126 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Justificación para agregar un nuevo método
to_numpy()
(además de array
) se agregó como resultado de las discusiones bajo dos temas de GitHub GH19954 y GH23623 .
Específicamente, los documentos mencionan la justificación:
[...] .values
no estaba claro si el valor devuelto sería la matriz real, alguna transformación de la misma o una de las matrices personalizadas de pandas (como Categorical
). Por ejemplo, con PeriodIndex
, .values
genera un nuevo objeto ndarray
de período cada vez. [...]
to_numpy
pretenden mejorar la consistencia de la API, que es un paso importante en la dirección correcta. .values
no quedará en desuso en la versión actual, pero espero que esto pueda suceder en algún momento en el futuro, por lo que instaría a los usuarios a migrar hacia la API más nueva, tan pronto como sea posible.
Crítica de otras soluciones
DataFrame.values
tiene un comportamiento inconsistente, como ya se señaló.
DataFrame.get_values()
es simplemente una envoltura DataFrame.values
, por lo que se aplica todo lo dicho anteriormente.
DataFrame.as_matrix()
ahora está en desuso, ¡ NO lo use!