Saya perlu mencari baris unik di a numpy.array
.
Sebagai contoh:
>>> a # I have
array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
>>> new_a # I want to get to
array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 0]])
Saya tahu bahwa saya dapat membuat satu set dan loop di atas array, tetapi saya mencari numpy
solusi murni yang efisien . Saya percaya bahwa ada cara untuk mengatur tipe data menjadi batal dan kemudian saya hanya bisa menggunakan numpy.unique
, tapi saya tidak tahu bagaimana cara membuatnya bekerja.
Jawaban:
Pada NumPy 1.13, seseorang dapat dengan mudah memilih sumbu untuk pemilihan nilai unik dalam sembarang N-dim array. Untuk mendapatkan baris unik, Anda dapat melakukan:
unique_rows = np.unique(original_array, axis=0)
sumber
np.unique(list_cor, axis=0)
membuat Anda array dengan baris duplikat dihapus ; itu tidak memfilter array ke elemen yang unik di array asli . Lihat di sini , misalnya ..original_array.sort(axis=1)
Namun solusi lain yang mungkin
sumber
np.vstack(list({tuple(row) for row in AIPbiased[i, :, :]}))
FutureWarning: array ke stack harus diteruskan sebagai tipe "sequence" seperti list atau tuple. Dukungan untuk iterables non-urutan seperti generator tidak digunakan lagi pada NumPy 1.16 dan akan meningkatkan kesalahan di masa mendatang.Opsi lain untuk penggunaan array terstruktur adalah menggunakan tampilan
void
tipe yang menggabungkan seluruh baris menjadi satu item:EDIT Ditambahkan
np.ascontiguousarray
berikut rekomendasi @ seberg. Ini akan memperlambat metode jika array belum berdekatan.EDIT Di atas dapat sedikit dipercepat, mungkin dengan mengorbankan kejelasan, dengan melakukan:
Juga, setidaknya pada sistem saya, kinerja bijaksana itu setara, atau bahkan lebih baik, daripada metode lexsort:
sumber
b = a.view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
?np.void
tipe data ukuran jumlah byte dalam satu baris penuh. Ini mirip dengan dua yang Anda dapatkan jika Anda memiliki arraynp.uint8
s dan melihatnya sebagainp.uint16
s, yang menggabungkan setiap dua kolom menjadi satu, tetapi lebih fleksibel.np.ascontiguousarray
atau serupa agar secara umum aman (saya tahu ini sedikit lebih ketat dari yang diperlukan, tapi ...). Baris harus bersebelahan agar tampilan berfungsi seperti yang diharapkan.np.unique
pada arraynp.void
pengembalian kesalahan terkait dengan mergesort tidak diimplementasikan untuk jenis itu. Ini berfungsi dengan baik di 1,7 sekalipun.-0.
tidak akan membandingkan sama dengan+0.
, sedangkan perbandingan elemen-oleh-elemen akan memiliki-0.==+0.
(seperti yang ditentukan oleh standar float ieee). Lihat stackoverflow.com/questions/26782038/…Jika Anda ingin menghindari biaya memori dari konversi ke serangkaian tupel atau struktur data serupa lainnya, Anda dapat mengeksploitasi susunan terstruktur numpy.
Caranya adalah dengan melihat array asli Anda sebagai array terstruktur di mana setiap item sesuai dengan deretan array asli. Ini tidak membuat salinan, dan cukup efisien.
Sebagai contoh cepat:
Untuk memahami apa yang terjadi, lihat hasil perantara.
Setelah kami melihat sesuatu sebagai array terstruktur, setiap elemen dalam array adalah baris di array asli Anda. (Pada dasarnya, ini adalah struktur data yang mirip dengan daftar tupel.)
Setelah kami jalankan
numpy.unique
, kami akan mendapatkan array terstruktur kembali:Yang kemudian perlu kita lihat sebagai array "normal" (
_
menyimpan hasil perhitungan terakhiripython
, itulah mengapa Anda melihatnya_.view...
):Dan kemudian membentuk kembali menjadi array 2D (
-1
adalah placeholder yang memberitahu numpy untuk menghitung jumlah baris yang benar, berikan jumlah kolom):Jelas, jika Anda ingin lebih ringkas, Anda bisa menuliskannya sebagai:
Yang mengakibatkan:
sumber
lexsort
. Saya pikir Anda merujuk menggunakan daftar tupel. Ya,lexsort
mungkin opsi yang lebih baik dalam hal ini. Saya sudah lupa tentang itu, dan melompat ke solusi yang terlalu rumit.np.unique
ketika saya menjalankannyanp.random.random(100).reshape(10,10)
mengembalikan semua elemen individu yang unik, tetapi Anda menginginkan baris yang unik, jadi pertama-tama Anda harus memasukkannya ke dalam tupel:Itulah satu-satunya cara saya melihat Anda mengubah jenis untuk melakukan apa yang Anda inginkan, dan saya tidak yakin apakah daftar iterasi yang akan diubah menjadi tuple tidak apa-apa dengan "tidak mengulangi" Anda.
sumber
< 100
baris per doa. Ini menggambarkan dengan tepat bagaimana melakukan unik atas baris dilakukan.uniques
mengandung elemen unik. Berpotensi saya salah memahami bentuk yang diharapkanarray
- bisakah Anda lebih tepat di sini?uniques
diurutkan (dan karena itu berbeda dari baris diarray
).B = np.array([[1,2],[2,1]]); A = np.unique([tuple(row) for row in B]); print(A) = array([[1, 2],[1, 2]])
np.unique bekerja dengan mengurutkan array yang diratakan, kemudian melihat apakah setiap item sama dengan sebelumnya. Ini dapat dilakukan secara manual tanpa perataan:
Metode ini tidak menggunakan tupel, dan harus jauh lebih cepat dan lebih sederhana daripada metode lain yang diberikan di sini.
CATATAN: Versi sebelumnya ini tidak memiliki ind tepat setelah [, yang berarti bahwa indeks yang salah digunakan. Juga, Joe Kington menunjukkan bahwa ini memang membuat berbagai salinan perantara. Metode berikut ini membuat lebih sedikit, dengan membuat salinan yang diurutkan dan kemudian menggunakan tampilan itu:
Ini lebih cepat dan menggunakan lebih sedikit memori.
Juga, jika Anda ingin menemukan baris unik di ndarray terlepas dari berapa banyak dimensi dalam array, berikut ini akan berfungsi:
Masalah yang tersisa yang menarik adalah jika Anda ingin mengurutkan / unik di sepanjang sumbu arbitrer dari array dimensi arbitrer, sesuatu yang akan lebih sulit.
Edit:
Untuk menunjukkan perbedaan kecepatan, saya menjalankan beberapa tes di ipython dari tiga metode berbeda yang dijelaskan dalam jawaban. Dengan a persis Anda , tidak ada banyak perbedaan, meskipun versi ini sedikit lebih cepat:
Namun, dengan versi yang lebih besar, versi ini menjadi jauh lebih cepat:
sumber
a[ind[1:]]
salinan, dll.) Di sisi lain, solusi Anda umumnya 2-3x lebih cepat daripada menambang sampai Anda kehabisan ram.dtype
dalam timing Anda? Saya pikir Anda salah. Di sistem saya, meneleponnp.unique
seperti yang dijelaskan dalam jawaban saya sedikit lebih cepat daripada menggunakan salah satu dari dua rasa Andanp.lexsort
. Dan ini sekitar 5x lebih cepat jika array untuk menemukan uniques memiliki bentuk(10000, 100)
. Bahkan jika Anda memutuskan untuk mengimplementasikan kembali apa yangnp.unique
dilakukan untuk memangkas waktu eksekusi (minor), mengecilkan setiap baris menjadi satu objek menjalankan perbandingan lebih cepat daripada harus memanggilnp.any
perbandingan kolom, terutama untuk jumlah kolom yang lebih tinggi.dtype
itu adila.dtype
, yaitu tipe data dari data yang dilihat, seperti yang dilakukan oleh Joe Kington dalam jawabannya. Jika ada banyak kolom, cara lain (tidak sempurna!) Untuk membuat hal-hal cepat menggunakanlexsort
adalah dengan hanya mengurutkan pada beberapa kolom. Ini khusus data karena orang perlu tahu kolom mana yang menyediakan varians yang cukup untuk disortir dengan sempurna. Misalnyaa.shape = (60000, 500)
- semacam pada 3 kolom pertama:ind = np.lexsort((a[:, 2], a[:, 1], a[:, 0]))
. Penghematan waktu cukup besar, tetapi penafian lagi: mungkin tidak menangkap semua kasus - itu tergantung pada data.Berikut adalah variasi lain untuk jawaban pygtonic @Greg
sumber
Saya telah membandingkan alternatif kecepatan yang disarankan dan menemukan bahwa, secara mengejutkan,
unique
solusi void view bahkan sedikit lebih cepat daripada numpy yang asliunique
denganaxis
argumen tersebut. Jika Anda mencari kecepatan, Anda pasti mauKode untuk mereproduksi plot:
sumber
vstack_dict
:, tidak pernah menggunakan dict, kurung kurawal adalah pemahaman set, dan oleh karena itu perilakunya hampir identik denganvstatck_set
. Karena,vstack_dict
garis kinerja hilang untuk grafik mondar-mandir, sepertinya itu hanya ditutupi olehvstack_set
grafik kinerja, karena mereka sangat mirip!vstack
varian.Saya tidak menyukai jawaban ini karena tidak ada yang menangani array titik mengambang dalam aljabar linear atau ruang vektor, di mana dua baris “sama” berarti “dalam beberapa 𝜀”. Satu jawaban yang memiliki ambang toleransi, https://stackoverflow.com/a/26867764/500207 , menganggap ambang tersebut sebagai elemen-bijaksana dan desimal presisi , yang berfungsi untuk beberapa kasus tetapi tidak secara matematis umum seperti jarak vektor benar.
Ini versi saya:
Fungsi domain publik di atas digunakan
scipy.spatial.distance.pdist
untuk menemukan jarak Euclidean (dapat disesuaikan) antara setiap pasangan baris. Kemudian membandingkan setiap jarak ke yangthresh
lama untuk menemukan baris yang berada dalamthresh
satu sama lain, dan mengembalikan hanya satu baris dari masing-masingthresh
-cluster.Seperti yang ditunjukkan, jarak
metric
tidak harus Euclidean -pdist
dapat menghitung jarak yang beragam termasukcityblock
(norma-Manhattan) dancosine
(sudut antara vektor).Jika
thresh=0
(default), maka baris harus agak tepat untuk dianggap "unik". Nilai bagus lainnya untukthresh
penggunaan presisi mesin skala, yaituthresh=np.spacing(1)*1e3
,.sumber
set
) sebagai perwakilan dari setiapthresh
lingkungan berukuran, fungsi dapat memungkinkan pengguna untuk menentukan cara memilih titik itu, misalnya, gunakan "median" atau titik terdekat dengan centroid, dll.thresh
cluster akan acak karena sifat unordered dariset
. Tentu saja itu adalah brainfart di bagian saya, yangset
toko tupel indeks yang berada dithresh
-neighborhood, jadi inifindRows
tidak pada kenyataannya kembali, untuk setiapthresh
-cluster, baris pertama di dalamnya.Mengapa tidak menggunakan
drop_duplicates
panda:sumber
The numpy_indexed paket (disclaimer: Saya penulisnya) membungkus solusi diposting oleh Jaime di nice dan diuji antarmuka, ditambah lagi banyak fitur:
sumber
np.unique works diberi daftar tuple:
Dengan daftar daftar yang dimunculkannya a
TypeError: unhashable type: 'list'
sumber
Berdasarkan jawaban di halaman ini saya telah menulis sebuah fungsi yang mereplikasi kemampuan
unique(input,'rows')
fungsi MATLAB , dengan fitur tambahan untuk menerima toleransi untuk memeriksa keunikan. Ini juga mengembalikan indeks sedemikian rupa sehinggac = data[ia,:]
dandata = c[ic,:]
. Silakan laporkan jika Anda melihat perbedaan atau kesalahan.sumber
Di luar @Jaime jawaban yang sangat baik, cara lain untuk menutup baris adalah dengan menggunakan
a.strides[0]
(dengan asumsia
C-berdekatan) yang sama dengana.dtype.itemsize*a.shape[0]
. Selanjutnyavoid(n)
adalah jalan pintas untukdtype((void,n))
. akhirnya kami sampai pada versi terpendek ini:Untuk
sumber
Untuk tujuan umum seperti 3D atau array bertingkat multidimensi yang lebih tinggi, coba ini:
yang memenuhi dataset 2D Anda:
memberi:
Tetapi juga array 3D seperti:
memberi:
sumber
unique
return_index
seperti yang dilakukan Jaime seharusnya membuatreturn
baris terakhir lebih sederhana. Cukup indekskan bagian asliar
pada sumbu kanan.Tidak satu pun dari jawaban ini yang berhasil untuk saya. Saya berasumsi karena baris unik saya berisi string dan bukan angka. Namun jawaban dari utas lain ini berhasil:
Sumber: https://stackoverflow.com/a/38461043/5402386
Anda dapat menggunakan metode daftar .count () dan .index ()
sumber
Kita benar-benar dapat mengubah array numpy numerik mxn menjadi array string numpy mx 1, silakan coba menggunakan fungsi berikut, ia menyediakan count , inverse_idx dan lain-lain, seperti numpy.unique:
Contoh:
sumber
Mari kita dapatkan seluruh matriks numpy sebagai daftar, lalu letakkan duplikat dari daftar ini, dan akhirnya kembalikan daftar unik kita kembali ke matriks numpy:
sumber
Solusi paling mudah adalah membuat baris-baris menjadi satu item dengan membuatnya menjadi string. Setiap baris kemudian dapat dibandingkan secara keseluruhan karena keunikannya menggunakan numpy. Solusi ini dapat digeneralisasi, Anda hanya perlu mengubah bentuk dan mengubah susunan array untuk kombinasi lainnya. Inilah solusi untuk masalah yang diberikan.
Akan memberi:
Kirim hadiah nobel saya melalui pos
sumber
sumber