Deprecare l'utilizzo di values
e as_matrix()
!
pandas v0.24.0 ha introdotto due nuovi metodi per ottenere matrici NumPy dagli oggetti pandas:
to_numpy()
, che è definito su Index
, Series,
e DataFrame
oggetti e
array
, che è definito su Index
e Series
solo oggetti.
Se visiti i documenti v0.24 per .values
, vedrai un grande avviso rosso che dice:
Avvertenza: si consiglia DataFrame.to_numpy()
invece di utilizzare .
Vedere questa sezione delle note sulla versione v0.24.0 e questa risposta per ulteriori informazioni.
Verso una migliore coerenza: to_numpy()
Nello spirito di una migliore coerenza in tutta l'API, to_numpy
è stato introdotto un nuovo metodo per estrarre l'array NumPy sottostante da 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]])
Come accennato in precedenza, questo metodo è anche definito su Index
e Series
oggetti (vedi qui ).
df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
Per impostazione predefinita, viene restituita una vista, quindi eventuali modifiche apportate influiranno sull'originale.
v = df.to_numpy()
v[0, 0] = -1
df
A B
a -1 4
b 2 5
c 3 6
Se invece hai bisogno di una copia, usa to_numpy(copy=True
).
panda> = 1.0 aggiornamento per ExtensionTypes
Se stai usando Panda 1.x, è probabile che avrai a che fare con tipi di estensione molto di più. Dovrai stare un po 'più attento che questi tipi di estensione vengano convertiti correttamente.
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])
Questo è richiamato nei documenti .
Se hai bisogno del dtypes
...
Come mostrato in un'altra risposta, DataFrame.to_records
è un buon modo per farlo.
df.to_records()
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
to_numpy
Purtroppo non è possibile farlo . Tuttavia, in alternativa, è possibile utilizzare 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')])
Per quanto riguarda le prestazioni, è quasi lo stesso (in realtà, l'utilizzo rec.fromrecords
è un po 'più veloce).
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)
Razionale per l'aggiunta di un nuovo metodo
to_numpy()
(oltre a array
) è stato aggiunto a seguito di discussioni nell'ambito di due numeri GitHub GH19954 e GH23623 .
In particolare, i documenti menzionano la logica:
[...] con .values
esso non era chiaro se il valore restituito sarebbe l'array effettivo, una sua trasformazione o uno degli array personalizzati di panda (come Categorical
). Ad esempio, con PeriodIndex
, .values
genera ndarray
ogni volta un nuovo oggetto periodico. [...]
to_numpy
mirare a migliorare la coerenza dell'API, che rappresenta un passo importante nella giusta direzione. .values
non sarà deprecato nella versione corrente, ma mi aspetto che ciò possa accadere ad un certo punto in futuro, quindi esorto gli utenti a migrare verso l'API più recente, appena possibile.
Critica di altre soluzioni
DataFrame.values
ha un comportamento incoerente, come già notato.
DataFrame.get_values()
è semplicemente un involucro in giro DataFrame.values
, quindi si applica tutto quanto detto sopra.
DataFrame.as_matrix()
è obsoleto ora, NON utilizzare!