заданий масив на зразок цілих чисел
[1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5]
Мені потрібно замаскувати елементи, які повторюються більше, ніж N
раз. Для уточнення: головна мета - отримати масив булевих масок, щоб згодом використовувати його для обчислень бінінгу.
Я придумав досить складне рішення
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)
даючи напр
bins[mask]
Out[90]: array([1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
Чи є кращий спосіб це зробити?
РЕДАКЦІЯ, №2
Дякую за відповіді! Ось тонка версія базового сюжету MSeifert. Дякую, що вказали на мене simple_benchmark
. Показано лише 4 найшвидших варіанти:
Висновок
Ідея, запропонована Флоріаном Н , модифікована Полом Панзером, здається, є прекрасним способом вирішення цієї проблеми, оскільки вона досить пряма вперед та лише numpy
. Якщо ви все добре не використовуєте numba
, рішення MSeifert перевершує інше.
Я вирішив прийняти відповідь MSeifert як рішення, оскільки це більш загальна відповідь: Він правильно обробляє довільні масиви з (не унікальними) блоками послідовних повторюваних елементів. У випадку, якщо numba
це не можна, відповідь Дівакара також варто переглянути!