Konversi panda dataframe ke array NumPy


467

Saya tertarik mengetahui cara mengubah kerangka data panda menjadi array NumPy.

bingkai data:

import numpy as np
import pandas as pd

index = [1, 2, 3, 4, 5, 6, 7]
a = [np.nan, np.nan, np.nan, 0.1, 0.1, 0.1, 0.1]
b = [0.2, np.nan, 0.2, 0.2, 0.2, np.nan, np.nan]
c = [np.nan, 0.5, 0.5, np.nan, 0.5, 0.5, np.nan]
df = pd.DataFrame({'A': a, 'B': b, 'C': c}, index=index)
df = df.rename_axis('ID')

memberi

label   A    B    C
ID                                 
1   NaN  0.2  NaN
2   NaN  NaN  0.5
3   NaN  0.2  0.5
4   0.1  0.2  NaN
5   0.1  0.2  0.5
6   0.1  NaN  0.5
7   0.1  NaN  NaN

Saya ingin mengonversikan ini menjadi array NumPy, seperti:

array([[ nan,  0.2,  nan],
       [ nan,  nan,  0.5],
       [ nan,  0.2,  0.5],
       [ 0.1,  0.2,  nan],
       [ 0.1,  0.2,  0.5],
       [ 0.1,  nan,  0.5],
       [ 0.1,  nan,  nan]])

Bagaimana saya bisa melakukan ini?


Sebagai bonus, mungkinkah untuk mempertahankan dtypes, seperti ini?

array([[ 1, nan,  0.2,  nan],
       [ 2, nan,  nan,  0.5],
       [ 3, nan,  0.2,  0.5],
       [ 4, 0.1,  0.2,  nan],
       [ 5, 0.1,  0.2,  0.5],
       [ 6, 0.1,  nan,  0.5],
       [ 7, 0.1,  nan,  nan]],
     dtype=[('ID', '<i4'), ('A', '<f8'), ('B', '<f8'), ('B', '<f8')])

atau serupa?


5
Mengapa Anda membutuhkan ini? Bukankah dataframe didasarkan pada array numpy? Anda harus dapat menggunakan kerangka data di mana Anda membutuhkan array yang numpy. Itu sebabnya Anda bisa menggunakan dataframe dengan scikit-belajar di mana fungsi meminta array numpy.
chrisfs

Berikut adalah beberapa tautan yang mungkin relevan tentang dtypes & recarrays (alias record array atau structured array): (1) stackoverflow.com/questions/9949427/… (2) stackoverflow.com/questions/52579601/…
JohnE

CATATAN: Harus mengonversi Pandas DataFrame ke array (atau daftar) seperti ini dapat menjadi indikasi masalah lainnya. Saya sangat menyarankan memastikan bahwa DataFrame adalah struktur data yang sesuai untuk kasus penggunaan khusus Anda, dan bahwa Pandas tidak menyertakan cara apa pun untuk melakukan operasi yang Anda minati.
AMC

Jawaban:


391

Untuk mengonversi panda dataframe (df) ke ndarray numpy, gunakan kode ini:

df.values

array([[nan, 0.2, nan],
       [nan, nan, 0.5],
       [nan, 0.2, 0.5],
       [0.1, 0.2, nan],
       [0.1, 0.2, 0.5],
       [0.1, nan, 0.5],
       [0.1, nan, nan]])

239

Hentikan penggunaan valuesdan as_matrix()!

pandas v0.24.0 memperkenalkan dua metode baru untuk mendapatkan array NumPy dari objek panda:

  1. to_numpy(), yang didefinisikan pada Index, Series,dan DataFrameobjek, dan
  2. array, yang didefinisikan Indexdan Serieshanya objek.

Jika Anda mengunjungi v0.24 docs for .values, Anda akan melihat peringatan merah besar yang mengatakan:

Peringatan: Sebaiknya gunakan DataFrame.to_numpy().

Lihat bagian ini dari catatan rilis v0.24.0 , dan jawaban ini untuk informasi lebih lanjut.


Menuju Konsistensi Yang Lebih Baik: to_numpy()

Dalam semangat konsistensi yang lebih baik di seluruh API, metode baru to_numpytelah diperkenalkan untuk mengekstrak array NumPy yang mendasarinya dari 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]])

Seperti disebutkan di atas, metode ini juga didefinisikan Indexdan Seriesobjek (lihat di sini ).

df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)

df['A'].to_numpy()
#  array([1, 2, 3])

Secara default, tampilan dikembalikan, sehingga setiap modifikasi yang dilakukan akan memengaruhi yang asli.

v = df.to_numpy()
v[0, 0] = -1

df
   A  B
a -1  4
b  2  5
c  3  6

Jika Anda membutuhkan salinan, gunakan to_numpy(copy=True).

panda> = 1.0 pembaruan untuk ExtensionTypes

Jika Anda menggunakan panda 1.x, kemungkinan Anda akan lebih sering berurusan dengan tipe ekstensi. Anda harus sedikit lebih berhati-hati agar jenis ekstensi ini dikonversi dengan benar.

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])

Ini disebut dalam dokumen .

Jika Anda membutuhkan dtypes...

Seperti yang ditunjukkan dalam jawaban lain, DataFrame.to_recordsadalah cara yang baik untuk melakukan ini.

df.to_records()
# rec.array([('a', -1, 4), ('b',  2, 5), ('c',  3, 6)],
#           dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8')])

to_numpySayangnya, ini tidak bisa dilakukan . Namun, sebagai alternatif, Anda dapat menggunakan 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')])

Dari segi kinerja, hampir sama (sebenarnya, menggunakan rec.fromrecordssedikit lebih cepat).

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)

Dasar Pemikiran untuk Menambahkan Metode Baru

to_numpy()(selain array) ditambahkan sebagai hasil dari diskusi di bawah dua masalah GitHub GH19954 dan GH23623 .

Secara khusus, dokumen menyebutkan alasannya:

[...] dengan .valuesitu tidak jelas apakah nilai yang dikembalikan akan menjadi array yang sebenarnya, beberapa transformasi, atau salah satu array kustom panda (seperti Categorical). Misalnya, dengan PeriodIndex, .values menghasilkan ndarrayobjek periode baru setiap kali. [...]

to_numpybertujuan untuk meningkatkan konsistensi API, yang merupakan langkah besar ke arah yang benar. .valuestidak akan ditinggalkan dalam versi saat ini, tetapi saya berharap ini dapat terjadi di beberapa titik di masa depan, jadi saya akan mendorong pengguna untuk bermigrasi ke API yang lebih baru, secepat Anda bisa.


Kritik atas Solusi Lain

DataFrame.values memiliki perilaku yang tidak konsisten, sebagaimana telah dicatat.

DataFrame.get_values()hanyalah pembungkus DataFrame.values, jadi semua yang dikatakan di atas berlaku.

DataFrame.as_matrix()sudah usang sekarang, JANGAN gunakan!


Saya tidak mengerti bagaimana mungkin untuk membaca halaman demi halaman orang-orang yang berteriak di bagian atas paru-paru mereka untuk beralih dari as_matrixke solusi lain, dalam hal ini, to_numpytanpa menjelaskan bagaimana memulihkan fungsi pemilihan kolom as_matrix! Saya yakin ada cara lain untuk memilih kolom, tetapi as_matrixsetidaknya salah satunya!
Jérémie

@ Jérémie selain yang sudah jelas df[[col1, col2']].to_numpy()? Tidak yakin mengapa Anda berpikir ingin mengiklankan alternatif yang diperbarui ke fungsi yang sudah tidak berlaku menjamin downvote pada jawabannya.
cs95

bagaimana jika beberapa kolom adalah tipe daftar. Bagaimana saya bisa membuat array bergelombang rata dari ini?
Moniba

@ Moniba Anda mungkin ingin meledakkan item daftar menjadi kolom / baris terpisah sesuai kebutuhan Anda terlebih dahulu.
cs95

Kecuali saya salah, mendapatkan lebih dari satu kolom dalam panggilan yang sama akan membuat semua data digabungkan menjadi satu array besar. Apakah saya melewatkan sesuatu?
Andrea Moro

128

Catatan : .as_matrix()Metode yang digunakan dalam jawaban ini sudah usang. Pandas 0.23.4 memperingatkan:

Metode .as_matrixakan dihapus di versi mendatang. Gunakan nilai. Sebaliknya


Panda memiliki sesuatu yang dibangun di ...

numpy_matrix = df.as_matrix()

memberi

array([[nan, 0.2, nan],
       [nan, nan, 0.5],
       [nan, 0.2, 0.5],
       [0.1, 0.2, nan],
       [0.1, 0.2, 0.5],
       [0.1, nan, 0.5],
       [0.1, nan, nan]])

30
Ini tidak memberikan array terstruktur, semua kolom bertipe dtype object.
sebix

14
"Tidak digunakan sejak versi 0.23.0: Gunakan DataFrame.values ​​sebagai gantinya." / "Metode ini disediakan untuk kompatibilitas mundur. Umumnya, disarankan untuk menggunakan '.Nilai'." - github.com/pandas-dev/pandas/blob/…
David J.

4
Ini sekarang sudah usang. Dari v0.24 dan seterusnya, silakan gunakan to_numpysebagai gantinya (bukan .valueskeduanya). Lebih lanjut di sini .
cs95

1
"FutureWarning: Method .as_matrix akan dihapus dalam versi yang akan datang. Gunakan .values ​​sebagai gantinya."
Farhad Maleki

66

Saya hanya akan rantai fungsi DataFrame.reset_index () dan DataFrame.values untuk mendapatkan representasi Numpy dari dataframe, termasuk indeks:

In [8]: df
Out[8]: 
          A         B         C
0 -0.982726  0.150726  0.691625
1  0.617297 -0.471879  0.505547
2  0.417123 -1.356803 -1.013499
3 -0.166363 -0.957758  1.178659
4 -0.164103  0.074516 -0.674325
5 -0.340169 -0.293698  1.231791
6 -1.062825  0.556273  1.508058
7  0.959610  0.247539  0.091333

[8 rows x 3 columns]

In [9]: df.reset_index().values
Out[9]:
array([[ 0.        , -0.98272574,  0.150726  ,  0.69162512],
       [ 1.        ,  0.61729734, -0.47187926,  0.50554728],
       [ 2.        ,  0.4171228 , -1.35680324, -1.01349922],
       [ 3.        , -0.16636303, -0.95775849,  1.17865945],
       [ 4.        , -0.16410334,  0.0745164 , -0.67432474],
       [ 5.        , -0.34016865, -0.29369841,  1.23179064],
       [ 6.        , -1.06282542,  0.55627285,  1.50805754],
       [ 7.        ,  0.95961001,  0.24753911,  0.09133339]])

Untuk mendapatkan dtypes, kita perlu mengubah ndarray ini menjadi array terstruktur menggunakan view :

In [10]: df.reset_index().values.ravel().view(dtype=[('index', int), ('A', float), ('B', float), ('C', float)])
Out[10]:
array([( 0, -0.98272574,  0.150726  ,  0.69162512),
       ( 1,  0.61729734, -0.47187926,  0.50554728),
       ( 2,  0.4171228 , -1.35680324, -1.01349922),
       ( 3, -0.16636303, -0.95775849,  1.17865945),
       ( 4, -0.16410334,  0.0745164 , -0.67432474),
       ( 5, -0.34016865, -0.29369841,  1.23179064),
       ( 6, -1.06282542,  0.55627285,  1.50805754),
       ( 7,  0.95961001,  0.24753911,  0.09133339),
       dtype=[('index', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')])

3
satu-satunya hal yang hilang dalam jawaban ini adalah bagaimana membangun dtype dari frame data sehingga Anda dapat menulis fungsi generik
Joseph Garvin

32

Anda dapat menggunakan to_recordsmetode ini, tetapi harus sedikit bermain-main dengan dtypes jika mereka tidak seperti yang Anda inginkan sejak awal. Dalam kasus saya, setelah menyalin DF Anda dari string, tipe indeks adalah string (diwakili oleh objectdtype dalam panda):

In [102]: df
Out[102]: 
label    A    B    C
ID                  
1      NaN  0.2  NaN
2      NaN  NaN  0.5
3      NaN  0.2  0.5
4      0.1  0.2  NaN
5      0.1  0.2  0.5
6      0.1  NaN  0.5
7      0.1  NaN  NaN

In [103]: df.index.dtype
Out[103]: dtype('object')
In [104]: df.to_records()
Out[104]: 
rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5),
       (4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5),
       (7, 0.1, nan, nan)], 
      dtype=[('index', '|O8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')])
In [106]: df.to_records().dtype
Out[106]: dtype([('index', '|O8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')])

Mengonversi tipe rekarray tidak berfungsi untuk saya, tetapi orang dapat melakukannya di Panda:

In [109]: df.index = df.index.astype('i8')
In [111]: df.to_records().view([('ID', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')])
Out[111]:
rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5),
       (4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5),
       (7, 0.1, nan, nan)], 
      dtype=[('ID', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')])

Perhatikan bahwa Pandas tidak menetapkan nama indeks dengan benar (ke ID) dalam array catatan yang diekspor (bug?), Jadi kami mendapat untung dari konversi jenis juga untuk memperbaiki itu.

Saat ini Pandas hanya memiliki integer 8-byte i8,, dan mengapung, f8(lihat masalah ini ).


2
Untuk mendapatkan array terstruktur yang dicari (yang memiliki kinerja lebih baik daripada recarray) Anda hanya meneruskan recarray ke np.arraykonstruktor.
meteore

Kami hanya melakukan perbaikan untuk mengatur nama indeks yang ditunjukkan di atas.
Chang She

26

Sepertinya df.to_records()akan bekerja untuk Anda. Fitur persis yang Anda cari diminta dan to_recordsditunjuk sebagai alternatif.

Saya mencoba ini secara lokal menggunakan contoh Anda, dan panggilan itu menghasilkan sesuatu yang sangat mirip dengan output yang Anda cari:

rec.array([(1, nan, 0.2, nan), (2, nan, nan, 0.5), (3, nan, 0.2, 0.5),
       (4, 0.1, 0.2, nan), (5, 0.1, 0.2, 0.5), (6, 0.1, nan, 0.5),
       (7, 0.1, nan, nan)],
      dtype=[(u'ID', '<i8'), (u'A', '<f8'), (u'B', '<f8'), (u'C', '<f8')])

Perhatikan bahwa ini recarraybukan array. Anda bisa memindahkan hasilnya ke array numpy biasa dengan memanggil konstruktornya sebagai np.array(df.to_records()).


3
Tunggu, apa yang ditambahkan jawaban ini dibandingkan dengan jawaban lain oleh @meteore yang disebutkan to_records()lebih dari 5 tahun sebelumnya?
JohnE

13

Coba ini:

a = numpy.asarray(df)

Hai! Silakan tambahkan beberapa penjelasan untuk jawaban Anda. Saat ini, saat ini sedang ditandai sebagai kualitas rendah oleh ulasan karena panjang dan konten dan berisiko dihapus oleh sistem. Terima kasih!
d_kennetz

1
pada dasarnya konversi input ke array (seperti namanya). Jadi seiring dengan konteks pertanyaan, jawaban ini valid. periksa docs.scipy.org/doc/numpy/reference/generated/…
Lautaro Parada Opazo

Terima kasih, saya pikir ini cukup jelas.
Dadu Khan

8

Berikut adalah pendekatan saya untuk membuat array struktur dari panda DataFrame.

Buat bingkai data

import pandas as pd
import numpy as np
import six

NaN = float('nan')
ID = [1, 2, 3, 4, 5, 6, 7]
A = [NaN, NaN, NaN, 0.1, 0.1, 0.1, 0.1]
B = [0.2, NaN, 0.2, 0.2, 0.2, NaN, NaN]
C = [NaN, 0.5, 0.5, NaN, 0.5, 0.5, NaN]
columns = {'A':A, 'B':B, 'C':C}
df = pd.DataFrame(columns, index=ID)
df.index.name = 'ID'
print(df)

      A    B    C
ID               
1   NaN  0.2  NaN
2   NaN  NaN  0.5
3   NaN  0.2  0.5
4   0.1  0.2  NaN
5   0.1  0.2  0.5
6   0.1  NaN  0.5
7   0.1  NaN  NaN

Tentukan fungsi untuk membuat array struktur numpy (bukan array rekaman) dari panda DataFrame.

def df_to_sarray(df):
    """
    Convert a pandas DataFrame object to a numpy structured array.
    This is functionally equivalent to but more efficient than
    np.array(df.to_array())

    :param df: the data frame to convert
    :return: a numpy structured array representation of df
    """

    v = df.values
    cols = df.columns

    if six.PY2:  # python 2 needs .encode() but 3 does not
        types = [(cols[i].encode(), df[k].dtype.type) for (i, k) in enumerate(cols)]
    else:
        types = [(cols[i], df[k].dtype.type) for (i, k) in enumerate(cols)]
    dtype = np.dtype(types)
    z = np.zeros(v.shape[0], dtype)
    for (i, k) in enumerate(z.dtype.names):
        z[k] = v[:, i]
    return z

Gunakan reset_indexuntuk membuat bingkai data baru yang menyertakan indeks sebagai bagian dari datanya. Konversi bingkai data itu ke susunan struktur.

sa = df_to_sarray(df.reset_index())
sa

array([(1L, nan, 0.2, nan), (2L, nan, nan, 0.5), (3L, nan, 0.2, 0.5),
       (4L, 0.1, 0.2, nan), (5L, 0.1, 0.2, 0.5), (6L, 0.1, nan, 0.5),
       (7L, 0.1, nan, nan)], 
      dtype=[('ID', '<i8'), ('A', '<f8'), ('B', '<f8'), ('C', '<f8')])

EDIT: Diperbarui df_to_sarray untuk menghindari kesalahan memanggil .encode () dengan python 3. Terima kasih kepada Joseph Garvin dan halcyon untuk komentar dan solusi mereka.


tidak berfungsi untuk saya, galat: TypeError: tipe data tidak dimengerti
Joseph Garvin

Terima kasih atas komentar Anda dan untuk halcyon untuk koreksi. Saya memperbarui jawaban saya jadi saya harap ini berhasil untuk Anda sekarang.
Phil


5

Cara Sederhana untuk Contoh DataFrame:

df

         gbm       nnet        reg
0  12.097439  12.047437  12.100953
1  12.109811  12.070209  12.095288
2  11.720734  11.622139  11.740523
3  11.824557  11.926414  11.926527
4  11.800868  11.727730  11.729737
5  12.490984  12.502440  12.530894

MENGGUNAKAN:

np.array(df.to_records().view(type=np.matrix))

DAPATKAN:

array([[(0, 12.097439  , 12.047437, 12.10095324),
        (1, 12.10981081, 12.070209, 12.09528824),
        (2, 11.72073428, 11.622139, 11.74052253),
        (3, 11.82455653, 11.926414, 11.92652727),
        (4, 11.80086775, 11.72773 , 11.72973699),
        (5, 12.49098389, 12.50244 , 12.53089367)]],
dtype=(numpy.record, [('index', '<i8'), ('gbm', '<f8'), ('nnet', '<f4'),
       ('reg', '<f8')]))

4

Hanya memiliki masalah yang sama ketika mengekspor dari dataframe ke arcgis table dan menemukan solusi dari usgs ( https://my.usgs.gov/confluence/display/cdi/pandas.DataFrame+to+ArcGIS+Table ). Singkatnya masalah Anda memiliki solusi serupa:

df

      A    B    C
ID               
1   NaN  0.2  NaN
2   NaN  NaN  0.5
3   NaN  0.2  0.5
4   0.1  0.2  NaN
5   0.1  0.2  0.5
6   0.1  NaN  0.5
7   0.1  NaN  NaN

np_data = np.array(np.rec.fromrecords(df.values))
np_names = df.dtypes.index.tolist()
np_data.dtype.names = tuple([name.encode('UTF8') for name in np_names])

np_data

array([( nan,  0.2,  nan), ( nan,  nan,  0.5), ( nan,  0.2,  0.5),
       ( 0.1,  0.2,  nan), ( 0.1,  0.2,  0.5), ( 0.1,  nan,  0.5),
       ( 0.1,  nan,  nan)], 
      dtype=(numpy.record, [('A', '<f8'), ('B', '<f8'), ('C', '<f8')]))

4

Saya membaca jawaban di atas. Metode " as_matrix () " berfungsi tetapi sudah usang sekarang. Bagi saya, Apa yang berhasil adalah " .to_numpy () ".

Ini mengembalikan array multidimensi. Saya lebih suka menggunakan metode ini jika Anda membaca data dari lembar excel dan Anda perlu mengakses data dari indeks apa pun. Semoga ini membantu :)


Apa yang Anda maksud dengan dan Anda perlu mengakses data dari indeks apa pun ? Bergantung pada sifat data Anda, Pandaf DataFrame bahkan mungkin bukan pilihan yang tepat.
AMC

2

Selanjutnya untuk jawaban meteore, saya menemukan kode

df.index = df.index.astype('i8')

tidak bekerja untuk saya. Jadi saya meletakkan kode saya di sini untuk kenyamanan orang lain yang terjebak dengan masalah ini.

city_cluster_df = pd.read_csv(text_filepath, encoding='utf-8')
# the field 'city_en' is a string, when converted to Numpy array, it will be an object
city_cluster_arr = city_cluster_df[['city_en','lat','lon','cluster','cluster_filtered']].to_records()
descr=city_cluster_arr.dtype.descr
# change the field 'city_en' to string type (the index for 'city_en' here is 1 because before the field is the row index of dataframe)
descr[1]=(descr[1][0], "S20")
newArr=city_cluster_arr.astype(np.dtype(descr))

1

Cara sederhana untuk mengonversi dataframe menjadi array numpy:

import pandas as pd
df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
df_to_array = df.to_numpy()
array([[1, 3],
   [2, 4]])

Penggunaan to_numpy didorong untuk menjaga konsistensi.

Referensi: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_numpy.html


apa perbedaan antara solusi yang disediakan oleh Arsam dan milik Anda ...
qaiser

Hanya mencoba membuatnya lebih lengkap dan dapat digunakan dengan contoh kode, yang merupakan pilihan pribadi saya.
user1460675

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.