diberi array bilangan bulat seperti
[1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5]
Saya perlu menutupi elemen yang berulang N
kali. Untuk memperjelas: tujuan utama adalah untuk mengambil array topeng boolean, untuk menggunakannya nanti untuk perhitungan binning.
Saya datang dengan solusi yang agak rumit
import numpy as np
bins = np.array([1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5])
N = 3
splits = np.split(bins, np.where(np.diff(bins) != 0)[0]+1)
mask = []
for s in splits:
if s.shape[0] <= N:
mask.append(np.ones(s.shape[0]).astype(np.bool_))
else:
mask.append(np.append(np.ones(N), np.zeros(s.shape[0]-N)).astype(np.bool_))
mask = np.concatenate(mask)
memberi misalnya
bins[mask]
Out[90]: array([1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
Apakah ada cara yang lebih baik untuk melakukan ini?
EDIT, # 2
Terima kasih banyak atas jawabannya! Berikut ini adalah versi ramping dari plot benchmark MSeifert. Terima kasih telah menunjuk saya simple_benchmark
. Hanya menampilkan 4 opsi tercepat:
Kesimpulan
Gagasan yang diajukan oleh Florian H , yang dimodifikasi oleh Paul Panzer tampaknya merupakan cara yang bagus untuk menyelesaikan masalah ini karena cukup lurus ke depan dan numpy
- hanya. Jika Anda baik-baik saja dengan menggunakan numba
, solusi MSeifert mengungguli yang lain.
Saya memilih untuk menerima jawaban MSeifert sebagai solusi karena ini adalah jawaban yang lebih umum: Ia dengan benar menangani array sewenang-wenang dengan blok (non-unik) elemen berulang berulang. Dalam hal numba
ini adalah no-go, jawaban Divakar juga patut dilihat!
Jawaban:
Saya ingin menghadirkan solusi menggunakan numba yang seharusnya cukup mudah dimengerti. Saya berasumsi bahwa Anda ingin "menutupi" item berulang berulang:
Sebagai contoh:
Kinerja:
Menggunakan
simple_benchmark
- namun saya belum memasukkan semua pendekatan. Ini skala log-log:Sepertinya solusi numba tidak dapat mengalahkan solusi dari Paul Panzer yang tampaknya lebih cepat untuk array besar sedikit (dan tidak memerlukan ketergantungan tambahan).
Namun keduanya tampaknya mengungguli solusi lain, tetapi mereka mengembalikan masker bukannya array yang "difilter".
sumber
out
argumen (atau mungkin bentuk fungsional operator), jadi saya tidak bisa menyimpan salinan itu. Tapi saya sangat sukasimple_benchmark
.simple_benchmark
! terima kasih untuk itu dan tentu saja terima kasih atas jawabannya. Karena saya menggunakannumba
untuk hal-hal lain juga, saya juga cenderung menggunakannya di sini dan menjadikan ini solusi. antara batu dan tempat yang keras di sana ...Penafian: ini hanya implementasi yang lebih baik dari ide @ FlorianH:
Untuk array yang lebih besar ini membuat perbedaan besar:
sumber
[1,1,1,1,2,2,1,1,2,2]
.Pendekatan # 1: Ini cara vektorisasi -
Contoh dijalankan -
Pendekatan # 2: Versi yang sedikit lebih ringkas -
Pendekatan # 3: Menggunakan hitungan yang dikelompokkan dan
np.repeat
(tidak akan memberi kita topeng) -Pendekatan # 4: Dengan
view-based
metode -Pendekatan # 5: Dengan
view-based
metode tanpa indeks dariflatnonzero
-sumber
Anda bisa melakukan ini dengan pengindeksan. Untuk N apa pun kodenya adalah:
keluaran:
sumber
timeit
berjalan.Sebuah banyak cara yang lebih baik akan menggunakan
numpy
'sunique()
-fungsi. Anda akan mendapatkan entri unik dalam array Anda dan juga hitungan seberapa sering mereka muncul:keluaran:
sumber
Anda bisa menggunakan loop sementara yang memeriksa apakah elemen array posisi N kembali sama dengan yang saat ini. Catatan solusi ini mengasumsikan array dipesan.
sumber
len(question)
kelen(bins)
Anda bisa menggunakan grouby untuk umum unsur-unsur kelompok dan daftar filter yang lebih panjang dari N .
sumber
Larutan
Anda bisa menggunakannya
numpy.unique
. Variabelfinal_mask
dapat digunakan untuk mengekstrak elemen traget dari arraybins
.Keluaran :
sumber
bins
, kan?final_values
langsung, Anda bisa tanda komentar baris hanya berkomentar dalam larutan dan dalam hal ini Anda bisa membuang tiga baris:mask = ...
,final_mask = ...
danbins[final_mask]
.