Preterir o uso de values
e as_matrix()
!
O pandas v0.24.0 introduziu dois novos métodos para obter matrizes NumPy a partir de objetos pandas:
to_numpy()
, que é definido em Index
, Series,
e DataFrame
objetos, e
array
, que é definido apenas Index
e Series
objetos.
Se você visitar os documentos da v0.24 para .values
, verá um grande aviso vermelho dizendo:
Aviso: Recomendamos o uso DataFrame.to_numpy()
.
Consulte esta seção das notas da versão v0.24.0 e esta resposta para obter mais informações.
Rumo a uma melhor consistência: to_numpy()
No espírito de melhor consistência em toda a API, um novo método to_numpy
foi introduzido para extrair a matriz NumPy subjacente dos 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 mencionado acima, este método também é definido em Index
e Series
objetos (veja aqui ).
df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
Por padrão, uma exibição é retornada, portanto, quaisquer modificações feitas afetarão o original.
v = df.to_numpy()
v[0, 0] = -1
df
A B
a -1 4
b 2 5
c 3 6
Se você precisar de uma cópia, use to_numpy(copy=True
).
pandas> = 1.0 atualização para ExtensionTypes
Se você estiver usando o pandas 1.x, é provável que esteja lidando com tipos de extensão muito mais. Você precisará ter um pouco mais de cuidado para que esses tipos de extensão sejam convertidos corretamente.
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])
Isso é mencionado nos documentos .
Se você precisar do dtypes
...
Como mostrado em outra resposta, DataFrame.to_records
é uma boa maneira de fazer isso.
df.to_records()
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
to_numpy
Infelizmente, isso não pode ser feito . No entanto, como alternativa, você pode 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')])
Em termos de desempenho, é quase o mesmo (na verdade, usar rec.fromrecords
é um pouco mais 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)
Justificativa para adicionar um novo método
to_numpy()
(além de array
) foi adicionado como resultado de discussões em duas edições do GitHub GH19954 e GH23623 .
Especificamente, os documentos mencionam a lógica:
[...] com .values
isso não ficou claro se o valor retornado seria a matriz real, alguma transformação dela ou uma das matrizes personalizadas dos pandas (como Categorical
). Por exemplo, com PeriodIndex
, .values
gera um novondarray
objeto de ponto a cada vez. [...]
to_numpy
visam melhorar a consistência da API, que é um passo importante na direção certa. .values
não será descontinuado na versão atual, mas espero que isso aconteça em algum momento no futuro. Por isso, exortaria os usuários a migrarem para a API mais recente assim que possível.
Crítica de outras soluções
DataFrame.values
tem comportamento inconsistente, como já observado.
DataFrame.get_values()
é simplesmente um invólucro DataFrame.values
, então tudo o que foi dito acima se aplica.
DataFrame.as_matrix()
está obsoleto agora, NÃO use!