Przestań używać values
i as_matrix()
!
panda v0.24.0 wprowadziła dwie nowe metody uzyskiwania tablic NumPy z obiektów pand:
to_numpy()
, Który jest zdefiniowany Index
, Series,
i DataFrame
obiektów, a
array
, który jest zdefiniowany Index
i dotyczy Series
tylko obiektów.
Jeśli odwiedzisz dokumentację v0.24 .values
, zobaczysz duże czerwone ostrzeżenie z napisem:
Ostrzeżenie: zalecamy użycie DataFrame.to_numpy()
zamiast tego.
Więcej informacji można znaleźć w tej sekcji informacji o wersji v0.24.0 i w tej odpowiedzi .
W kierunku lepszej spójności: to_numpy()
W duchu lepszej spójności w całym interfejsie API wprowadzono nową metodę to_numpy
wydobywania bazowej tablicy NumPy z 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]])
Jak wspomniano powyżej, ta metoda jest również zdefiniowana w obiektach Index
i Series
obiektach (patrz tutaj ).
df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
Domyślnie widok jest zwracany, więc wszelkie dokonane modyfikacje wpłyną na oryginał.
v = df.to_numpy()
v[0, 0] = -1
df
A B
a -1 4
b 2 5
c 3 6
Jeśli zamiast tego potrzebujesz kopii, użyj to_numpy(copy=True
).
panda> = aktualizacja 1.0 dla ExtensionTypes
Jeśli używasz pand 1.x, prawdopodobnie będziesz miał do czynienia z typami rozszerzeń o wiele więcej. Musisz być trochę bardziej ostrożny, aby te typy rozszerzeń zostały poprawnie przekonwertowane.
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])
Jest to przywołane w dokumentach .
Jeśli potrzebujesz dtypes
...
Jak pokazano w innej odpowiedzi, DataFrame.to_records
jest to dobry sposób na zrobienie tego.
df.to_records()
# rec.array([('a', -1, 4), ('b', 2, 5), ('c', 3, 6)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])
to_numpy
Niestety nie da się tego zrobić . Alternatywnie możesz użyć 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')])
Pod względem wydajności jest prawie taki sam (w rzeczywistości korzystanie rec.fromrecords
jest nieco szybsze).
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)
Uzasadnienie dodania nowej metody
to_numpy()
(oprócz array
) dodano w wyniku dyskusji na temat dwóch zagadnień GitHub: GH19954 i GH23623 .
W szczególności dokumenty wspominają o uzasadnieniu:
[...] .values
nie było jasne, czy zwrócona wartość będzie rzeczywistą tablicą, jakąś jej transformacją, czy jedną z niestandardowych tablic pand (jak Categorical
). Na przykład, z PeriodIndex
, .values
generuje nowy ndarray
okresu obiektów za każdym razem. [...]
to_numpy
dążyć do poprawy spójności interfejsu API, co stanowi duży krok we właściwym kierunku. .values
nie będzie przestarzałe w bieżącej wersji, ale spodziewam się, że tak się stanie w przyszłości, więc zachęcam użytkowników do migracji w kierunku nowszego interfejsu API, tak szybko, jak to możliwe.
Krytyka innych rozwiązań
DataFrame.values
ma niespójne zachowanie, jak już wspomniano.
DataFrame.get_values()
to po prostu opakowanie DataFrame.values
, więc wszystko, co powiedziano powyżej, ma zastosowanie.
DataFrame.as_matrix()
jest przestarzałe, NIE używaj!