Припиніть використання values
та as_matrix()
!
pandas v0.24.0 представив два нові методи отримання масивів NumPy з об'єктів pandas:
to_numpy()
, що визначено на Index
, Series,
і DataFrame
об'єкти, і
array
, Який визначається на Index
і Series
тільки об'єкти.
Якщо ви відвідаєте документи v0.24 для .values
, ви побачите велике червоне попередження, яке говорить:
Попередження: радимо використовувати DataFrame.to_numpy()
замість цього.
Дивіться цей розділ приміток до випуску v0.24.0 і цю відповідь для отримання додаткової інформації.
Назустріч кращій послідовності: to_numpy()
У дусі кращої послідовності в API to_numpy
було введено новий метод для вилучення базового масиву NumPy з 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]])
Як було сказано вище, цей метод також визначений на об'єктах Index
і Series
(див. Тут ).
df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
За замовчуванням подання повертається, тому будь-які внесені зміни впливатимуть на оригінал.
v = df.to_numpy()
v[0, 0] = -1
df
A B
a -1 4
b 2 5
c 3 6
Якщо вам потрібна копія, використовуйте to_numpy(copy=True
).
pandas> = 1,0 оновлення для ExtensionTypes
Якщо ви використовуєте панди 1.x, швидше за все, ви будете мати справу з типами розширень набагато більше. Вам доведеться бути трохи уважнішими, щоб ці типи розширень були правильно перетворені.
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])
Це називається в документах .
Якщо вам потрібно dtypes
...
Як показано в іншій відповіді, DataFrame.to_records
це хороший спосіб зробити це.
df.to_records()
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
На to_numpy
жаль, це неможливо зробити . Однак в якості альтернативи можна використовувати 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')])
Ефективність, майже однакова (фактично, використання rec.fromrecords
трохи швидше).
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)
Обґрунтування додавання нового методу
to_numpy()
(на додаток до array
) було додано в результаті обговорень під двома випусками GitHub GH19954 та GH23623 .
Конкретно в документах згадується обгрунтування:
[...] з .values
ним було незрозуміло, чи буде повернене значення фактичним масивом, деяким перетворенням його чи одним із користувацьких масивів панди (як Categorical
). Наприклад, з PeriodIndex
, кожного разу .values
створює нові ndarray
об'єкти періоду. [...]
to_numpy
прагнуть покращити узгодженість API, що є головним кроком у правильному напрямку. .values
у поточній версії не буде застарілим, але я думаю, що це може статися в якийсь момент у майбутньому, тому я закликаю користувачів перейти до новішого API, як тільки ви зможете.
Критика інших рішень
DataFrame.values
має непослідовну поведінку, як уже зазначалося.
DataFrame.get_values()
це просто обгортка навколо DataFrame.values
, тому все сказане вище стосується.
DataFrame.as_matrix()
тепер застаріло, НЕ використовуйте!