Подсчет значений в перекрывающихся скользящих окнах в python

Ваше объявление float содержит две части:

  1. Объявляет, что переменная timeRemaining имеет тип float.
  2. Он присваивает значение 0.58 к этой переменной.

Проблема возникает в части 2.

Правая часть оценивается сама по себе. Согласно спецификации C #, число, содержащее десятичную точку, которая не имеет суффикса, интерпретируется как double.

Итак, теперь мы имеем значение double, которое мы хотим присвоить переменная типа float. Для этого должно быть неявное преобразование из double в float. Нет такого преобразования, потому что вы можете (и в этом случае делать) потерять информацию в процессе преобразования.

Причина в том, что значение, используемое компилятором, на самом деле не 0.58, но с плавающей запятой значение, самое близкое к 0,58, которое составляет 0,57999999999999978655962351581366 ... для double и ровно 0,579999946057796478271484375 для float.

Строго говоря, f не требуется. Вы можете избежать использования суффикса f, выставив значение в значение float:

float timeRemaining = (float)0.58;
2
задан Michael Hall 17 January 2019 в 13:43
поделиться

3 ответа

Количество элементов в корзине b - это количество элементов <= b.end минус количество элементов < b.start.

Таким образом, вы можете создать starts массив бинов, отсортированных по началу, и ends массив бинов, отсортированных по концу. Затем пройдитесь по всем 3 массивам в шаге. Когда вы продвигаетесь после каждого x в a, продвигайтесь дальше, начиная с x < b.start и , вычитая position_in_a из числа для этого бина. Затем продвиньтесь до конца с помощью x <= b.end и и добавьте position_in_a к счету для этого бина.

Общая сложность составляет O (N log N), где преобладает сортировка начального и конечного массивов. Ходить по 3 массивам и корректировать счет - O (N).

В своем коде вы генерируете массив уже отсортированных бинов, так что если вы можете сделать это, то можете пропустить этап сортировки, и общая сложность равна O (a.length + bin_count). Я бы не стал даже создавать этот массив, поскольку вы можете легко рассчитать начальное и конечное значения по индексу.

0
ответ дан Matt Timmermans 17 January 2019 в 13:43
поделиться

Примерно так (?):

def sliding_count(a, nx0, nx1, window):
    bin0 = np.arange(nx0,nx1,1)
    bin1 = bin0 + window 
    count = np.zeros((nx1-nx0), dtype=int)

    for j in range(nx1-nx0):
        count[j] = np.sum(a<=bin1[j]) - np.sum(a<bin0[j])
    return count

#---- main ---------------  
nx0, nx1, window = 0, 11, 10
a = np.array([1, 5, 8, 11, 14, 19])
sliding_count(a, nx0, nx1, window)

array([3, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3])

Я не проверял код для nx0> 0 и step> 1 в bin0 = np.arange (nx0, nx1,1) . Таким образом, длина цикла for должна быть изменена для таких случаев.

0
ответ дан pyano 17 January 2019 в 13:43
поделиться
import numpy as np

def alt(a, end, window, start=0, step=1):
    bin_starts = np.arange(start, end+1-window, step)
    bin_ends = bin_starts + window
    last_index = np.searchsorted(a, bin_ends, side='right')
    first_index = np.searchsorted(a, bin_starts, side='left')
    return  last_index - first_index

def sliding_count(a, end, window, start=0, step=1):
    bins = [(x, x + window) for x in range(start, (end + 1) - window, step)]
    counts = np.zeros(len(bins))
    for i, rng in enumerate(bins):
        count = len(a[np.where(np.logical_and(a>=rng[0], a<=rng[1]))])
        counts[i] = count
    return counts

a = np.array([1, 5, 8, 11, 14, 19])
end = 20
window = 10

print(sliding_count(a, end, window))
# [3. 4. 3. 3. 4. 4. 3. 3. 3. 3. 3.]

print(alt(a, end, window))
# [3 4 3 3 4 4 3 3 3 3 3]

Как работает alt:

Генерация начальных и конечных значений бинов:

In [73]: bin_starts = np.arange(start, end+1-window, step); bin_starts
Out[73]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

In [74]: bin_ends = bin_starts + window; bin_ends
Out[74]: array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])

Поскольку a в отсортированном порядке, вы можете использовать np.searchsorted найти первый и последний индекс в bin_starts и bin_ends, где подходит каждое значение в a:

In [75]: last_index = np.searchsorted(a, bin_ends, side='right'); last_index
Out[75]: array([3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6])

In [76]: first_index = np.searchsorted(a, bin_starts, side='left'); first_index
Out[76]: array([0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3])

count - это просто разница в индексах:

In [77]: last_index - first_index
Out[77]: array([3, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3])

Вот перфплот , сравнивающий производительность alt с sliding_count как функцию длины a:

import perfplot

def make_array(N):
    a = np.random.randint(10, size=N)
    a = a.cumsum()
    return a

def using_sliding(a):
    return sliding_count(a, end, window)

def using_alt(a):
    return alt(a, end, window)

perfplot.show(
    setup=make_array,
    kernels=[using_sliding, using_alt],
    n_range=[2**k for k in range(22)],
    logx=True,
    logy=True,
    xlabel='len(a)')

enter image description here

Perfplot также проверяет, что значение, возвращаемое using_sliding, равно значению, возвращенному using_alt.

Идея Мэтта Тиммерманса , « вычесть position_in_a из подсчета для этого бина » привела в действие это решение.

0
ответ дан unutbu 17 January 2019 в 13:43
поделиться
Другие вопросы по тегам:

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