Python: получить последние n истин из логического массива - PullRequest
0 голосов
/ 03 мая 2018

У меня есть логический массив и я хочу преобразовать его в массив, где только значения last_n_trues True все еще True. Простой пример:

>>> boolean_array = [False, False, True, True, True, False, False]
>>> last_n_trues = 2
>>> desired_output = [False, False, False, True, True, False, False]

Мой подход:

>>> import numpy as np
>>> idxs_of_trues = np.where(boolean_array)[0] 
array([2, 3, 4], dtype=int64)

>>> idxs_of_trues_last_n = idxs_of_trues[-last_n_trues:] 
array([3, 4], dtype=int64)

>>> [x in idxs_of_trues_last_n for x in range(0, len(boolean_array))]
[False, False, False, True, True, False, False]

Есть ли более быстрый способ сделать это? Особенно понимание списка кажется мне довольно сложным ...

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

Самый быстрый способ без библиотек - клонировать список и перебрать его в обратном порядке:

def foo(bools, last_n_trues):
    result = bools[:]
    count = 0
    for i in range(len(bools) - 1, -1, -1):
        if count < last_n_trues:
            if result[i]:
                count += 1
        else:       
            result[i] = False
    return result
0 голосов
/ 03 мая 2018

Подход № 1: Вот один с cumsum -

def keep_lastNTrue_cumsum(a, n):
    c = np.count_nonzero(a) # or a.sum()
    a[c - a.cumsum() >= n] = 0
    return a

Подход № 2: Еще два с argpartition -

def keep_lastNTrue_argpartition1(a, n):
    c = np.count_nonzero(a) # or a.sum()
    a[np.sort(np.argpartition(a,-n)[-c:])[:-n]] = 0
    return a

def keep_lastNTrue_argpartition2(a, n):
    c = np.count_nonzero(a) # or a.sum()
    p = np.argpartition(a,-n)[-a.sum():]
    cn = c-n
    idx = np.argpartition(p,cn)
    a[p[idx[:cn]]] = 0
    return a

Подход № 3: Другой с немного большим использованием маски -

def keep_lastNTrue_allmask(a, n):
    c = a.sum()
    set_mask = np.ones(c, dtype=bool)
    set_mask[:-n] = False
    a[a] = set_mask
    return a

Примеры прогонов -

In [141]: boolean_array = np.array([False, False, True, True, True, False, False])

In [142]: keep_lastNTrue_cumsum(boolean_array, n=2)
Out[142]: array([False, False, False,  True,  True, False, False])

In [143]: boolean_array = np.array([False, False, True, True, True, False, False])

In [144]: keep_lastNTrue_argpartition1(boolean_array, n=2)
Out[144]: array([False, False, False,  True,  True, False, False])

In [145]: boolean_array = np.array([False, False, True, True, True, False, False])

In [146]: keep_lastNTrue_argpartition2(boolean_array, n=2)
Out[146]: array([False, False, False,  True,  True, False, False])
0 голосов
/ 03 мая 2018

Вы должны просто иметь возможность просто использовать np.where

In [116]: x
Out[116]: array([False, False,  True,  True,  True, False, False], dtype=bool)

In [117]: x[np.where(x)[0][:-2]] = False

In [118]: x
Out[118]: array([False, False, False,  True,  True, False, False], dtype=bool)

Это просто заменяет все True, которые не являются последними 2, False

Это будет работать только в том случае, если x - это np.array, поэтому убедитесь, что перед этим попробуйте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...