У меня есть массив NumPy следующим образом:

import numpy as np
a = np.array([1, 4, 2, 6, 4, 4, 6, 2, 7, 6, 2, 8, 9, 3, 6, 3, 4, 4, 5, 8])

И постоянное число b = 6

На основе предыдущий вопрос Я могу посчитать число c, которое определяется числом раз, когда элементы в a меньше b 2 или более раз подряд ,

from itertools import groupby
b = 6
sum(len(list(g))>=2 for i, g in groupby(a < b) if i)

Так что в этом примере c == 3

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

Таким образом, с этим примером правильный вывод будет:

array1 = [1, 4, 2]
array2 = [4, 4]
array3 = [3, 4, 4, 5]

Поскольку:

1, 4, 2, 6, 4, 4, 6, 2, 7, 6, 2, 8, 9, 3, 6, 3, 4, 4, 5, 8  # numbers in a
1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0  # (a<b)
^^^^^^^-----^^^^-----------------------------^^^^^^^^^^---  # (a<b) 2+ times consecutively
   1         2                                    3

До сих пор я пробовал разные варианты:

np.isin((len(list(g))>=2 for i, g in groupby(a < b)if i), a)

А также

np.extract((len(list(g))>=2 for i, g in groupby(a < b)if i), a)

Но никто из них не достиг того, что я ищу. Может ли кто-нибудь указать мне правильные инструменты Python для вывода различных массивов, удовлетворяющих моему условию?

4
steve 4 Июл 2019 в 15:41

2 ответа

Лучший ответ

При измерении производительности моего другого ответа я заметил, что, хотя он был быстрее, чем Решение Остина (для массивов длиной <15000), его сложность не была линейной.

Основываясь на этом ответе, я нашел следующее решение, используя np.split, что более эффективно, чем оба ранее добавленных ответа:

array = np.append(a, -np.inf)  # padding so we don't lose last element
mask = array >= 6  # values to be removed
split_indices = np.where(mask)[0]
for subarray in np.split(array, split_indices + 1):
    if len(subarray) > 2:
        print(subarray[:-1])

Дает:

[1. 4. 2.]
[4. 4.]
[3. 4. 4. 5.]

Производительность*:

enter image description here

* Измерено с помощью perfplot

2
Georgy 5 Июл 2019 в 13:58

Используйте groupby и возьмите группы:

from itertools import groupby

lst = []
b = 6
for i, g in groupby(a, key=lambda x: x < b):
    grp = list(g)
    if i and len(grp) >= 2:
        lst.append(grp)

print(lst)

# [[1, 4, 2], [4, 4], [3, 4, 4, 5]]
1
Austin 4 Июл 2019 в 12:55