biorąc pod uwagę tablicę liczb całkowitych takich jak
[1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5]
Muszę zamaskować elementy, które powtarzają się więcej niż N
razy. Wyjaśnienie: głównym celem jest odzyskanie tablicy maski logicznej, aby później użyć jej do obliczeń binningu.
Wymyśliłem dość skomplikowane rozwiązanie
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)
podając np
bins[mask]
Out[90]: array([1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
Czy jest na to lepszy sposób?
EDYCJA, # 2
Wielkie dzięki za odpowiedzi! Oto szczupła wersja wykresu porównawczego MSeifert. Dzięki za wskazanie mnie do simple_benchmark
. Pokazuje tylko 4 najszybsze opcje:
Wniosek
Pomysł zaproponowany przez Floriana H , zmodyfikowany przez Paula Panzera, wydaje się być świetnym sposobem na rozwiązanie tego problemu, ponieważ jest dość prosty i numpy
tylko. Jeśli jesteś w porządku z użyciem numba
jednak rozwiązanie MSeifert za wyprzedza drugiego.
Zdecydowałem się zaakceptować odpowiedź MSeiferta jako rozwiązanie, ponieważ jest to bardziej ogólna odpowiedź: poprawnie obsługuje dowolne tablice z (nieunikalnymi) blokami kolejnych powtarzających się elementów. Na wypadek, gdyby numba
było to niemożliwe, odpowiedź Divakara również jest warta obejrzenia!
Odpowiedzi:
Chcę przedstawić rozwiązanie z użyciem Numby, które powinno być dość łatwe do zrozumienia. Zakładam, że chcesz „zamaskować” kolejne powtarzające się elementy:
Na przykład:
Wydajność:
Korzystanie
simple_benchmark
- jednak nie uwzględniłem wszystkich podejść. Jest to skala dziennika:Wygląda na to, że rozwiązanie numba nie jest w stanie pokonać rozwiązania Paula Panzera, który wydaje się być szybszy w przypadku dużych tablic (i nie wymaga dodatkowej zależności).
Jednak oba wydają się przewyższać inne rozwiązania, ale zwracają maskę zamiast „filtrowanej” tablicy.
źródło
out
argumentu (a może funkcjonalnej formy operatora), więc nie mogłem zapisać tej kopii. Przy okazji lubięsimple_benchmark
.simple_benchmark
! dzięki za to i oczywiście za odpowiedź. Ponieważ używam równieżnumba
do innych rzeczy, jestem skłonny również użyć go tutaj i uczynić to rozwiązaniem. między skałą a trudnym miejscem ...Oświadczenie: jest to tylko realizacja pomysłu @ FlorianH:
W przypadku większych tablic robi to ogromną różnicę:
źródło
[1,1,1,1,2,2,1,1,2,2]
.Podejście nr 1: Oto wektorowy sposób -
Przykładowy przebieg -
Podejście nr 2: Trochę bardziej kompaktowa wersja -
Podejście nr 3: używając zgrupowanych liczników i
np.repeat
(nie da nam maski) -Podejście # 4: Przy
view-based
metodzie -Zbliżać # 5: Przy
view-based
metodzie bez indeksów odflatnonzero
-źródło
Możesz to zrobić za pomocą indeksowania. Dla każdego N kod będzie:
wynik:
źródło
timeit
biegach.O wiele ładniejszy sposób byłoby użyć
numpy
„sunique()
-function. Otrzymasz unikalne wpisy w swojej tablicy oraz liczbę wyświetleń:wynik:
źródło
Możesz użyć pętli while, która sprawdza, czy element tablicy N pozycji wstecz jest równy bieżącej. Uwaga: to rozwiązanie zakłada, że tablica jest uporządkowana.
źródło
len(question)
nalen(bins)
Można użyć grouby do grupy wspólnych elementów i listy filtrów, które są dłuższe niż N .
źródło
Rozwiązanie
Możesz użyć
numpy.unique
. Zmiennejfinal_mask
można użyć do wyodrębnienia elementów tragetu z tablicybins
.Wyjście :
źródło
bins
, prawda?final_values
bezpośrednio, można odkomentowaniu jedyny skomentował linię w roztworze iw tym przypadku można wyrzucić trzy wiersze:mask = ...
,final_mask = ...
ibins[final_mask]
.