найдите длину последовательностей идентичных значений в массиве numpy (кодирование по длинам серий)

Я бы не пошел с MSTest. Хотя это, вероятно, самое перспективное доказательство наличия фреймворков с Microsoft, это не самое гибкое решение. Он не будет работать в одиночестве без некоторых хаков. Поэтому запустить его на сервере сборки, отличном от TFS, без установки Visual Studio сложно. Визуальный тестовый прогон на самом деле медленнее, чем Testdriven.Net + любой другой фреймворк. А поскольку выпуски этой среды привязаны к выпускам Visual Studio, обновлений меньше, и если вам приходится работать со старыми VS, вы привязаны к более старому MSTest.

Я не думаю, что это имеет большое значение, какие другие фреймворки вы используете. Это действительно легко переключаться с одного на другой.

Я лично использую XUnit.Net или NUnit в зависимости от предпочтений моих коллег. NUnit является самым стандартным. XUnit.Net является самой простой структурой.

48
задан Thomas Browne 14 November 2017 в 12:02
поделиться

4 ответа

Хотя и не numpy примитивы, функции itertools часто бывают очень быстрыми, так что попробуйте эту функцию (и измерьте время для различных решений, включая это один, конечно):

def runs_of_ones(bits):
  for bit, group in itertools.groupby(bits):
    if bit: yield sum(group)

Если вам действительно нужны значения в списке, конечно, вы можете просто использовать list (run_of_ones (bits)); но, возможно, понимание списка может быть еще немного быстрее:

def runs_of_ones_list(bits):
  return [sum(g) for b, g in itertools.groupby(bits) if b]

Переходя к «естественным для numpy» возможностям, как насчет:

def runs_of_ones_array(bits):
  # make sure all runs of ones are well-bounded
  bounded = numpy.hstack(([0], bits, [0]))
  # get 1 at run starts and -1 at run ends
  difs = numpy.diff(bounded)
  run_starts, = numpy.where(difs > 0)
  run_ends, = numpy.where(difs < 0)
  return run_ends - run_starts

Опять же: не забудьте сравнить решения друг с другом на реалистичных для вас примерах!

47
ответ дан 26 November 2019 в 18:41
поделиться

Here is a solution using only arrays: it takes an array containing a sequence of bools and counts the length of the transitions.

>>> from numpy import array, arange
>>> b = array([0,0,0,1,1,1,0,0,0,1,1,1,1,0,0], dtype=bool)
>>> sw = (b[:-1] ^ b[1:]); print sw
[False False  True False False  True False False  True False False False
  True False]
>>> isw = arange(len(sw))[sw]; print isw
[ 2  5  8 12]
>>> lens = isw[1::2] - isw[::2]; print lens
[3 4]

sw contains a true where there is a switch, isw converts them in indexes. The items of isw are then subtracted pairwise in lens.

Notice that if the sequence started with an 1 it would count the length of the 0s sequences: this can be fixed in the indexing to compute lens. Also, I have not tested corner cases such sequences of length 1.


Full function that returns start positions and lengths of all True-subarrays.

import numpy as np

def count_adjacent_true(arr):
    assert len(arr.shape) == 1
    assert arr.dtype == np.bool
    if arr.size == 0:
        return np.empty(0, dtype=int), np.empty(0, dtype=int)
    sw = np.insert(arr[1:] ^ arr[:-1], [0, arr.shape[0]-1], values=True)
    swi = np.arange(sw.shape[0])[sw]
    offset = 0 if arr[0] else 1
    lengths = swi[offset+1::2] - swi[offset:-1:2]
    return swi[offset:-1:2], lengths

Tested for different bool 1D-arrays (empty array; single/multiple elements; even/odd lengths; started with True/False; with only True/False elements).

9
ответ дан 26 November 2019 в 18:41
поделиться

Просто в случае, если кому-то интересно (и поскольку вы упомянули MATLAB мимоходом), вот один из способов решить эту проблему в MATLAB:

threshold = 7;
d = 10*rand(1,100000);  % Sample data
b = diff([false (d < threshold) false]);
durations = find(b == -1)-find(b == 1);

Я не слишком хорошо знаком с Python, но, возможно, это может помочь вам дать некоторые идеи. =)

6
ответ дан 26 November 2019 в 18:41
поделиться
durations = []
counter   = 0

for bool in b:
    if bool:
        counter += 1
    elif counter > 0:
        durations.append(counter)
        counter = 0

if counter > 0:
    durations.append(counter)
0
ответ дан 26 November 2019 в 18:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: