Как кластеризовать непрерывные пики - PullRequest
1 голос
/ 03 июня 2019

У меня есть пример данных о разных ценах на один продукт и сколько раз они были введены в базу данных. Моя цель - определить оптимальный диапазон (-ы) цены для продукта на основе его частоты в наборе данных.

Это частотно-частотный график:

Frequency Plot

Я использую Python 3.7.1 на Jupyter. Я попытался использовать функцию peak_widths из библиотеки сигналов. Я получил ширину пиков, их начальные и конечные точки. Я сделал логику цикла if-else, но мне кажется, что я где-то ошибаюсь, я получаю только один кластер.

Я использовал это, чтобы получить ширину пика

from scipy.signal import peak_widths
pkwdh_106 = signal.peak_widths(count_106, index_106, rel_height=1)
plt.plot(index_106, count_106[index_106], "o"); plt.plot(count_106)
plt.hlines(*pkwdh_106[1:])
plt.xlabel('Price')
plt.ylabel('Frequency')

Это информация о пиках

Width of each peak / maxima :  [7. 5. 4. 7. 2.88888889]
Y level of each width :  [1. 1. 1. 1. 2.]
Starting point of each width :  [ 8. 15. 20. 36. 40.]
Ending point of each width :  [15. 20. 24. 43. 42.88888889]

Это цикл, который я пробовал, но здесь чего-то не хватает.

sum_width = 0
name='cluster('+str(i)+')'
name=[]

start = len(start_x) # Length of starting array is 5
end = len(end_x) # Length of ending array is 5

for i in range(end-1):
    # Iterating till 4 END elements
    for j in range(start-1):
        # Iterating till 4 START elements
        if end_x[i]>=start_x[j+1]:
            # If ending of 1st width is greater than or equal to starting of 2nd width
            sum_width = sum_width + width[i]
            # Add starting of 1st width length to the total sum variable
            name.append(width[i])
            # Adding the width lengths to an array
            print('If loop total width - ', sum_width)
            print('If loop ', name)
        else:
            sum_width = sum_width + width[i]
            # If ending of 1st width is lesser than the starting of 2nd width
            name.append(width[i])
            # Add starting of 1st width length to the total sum variable
            print('Else loop total width - ', sum_width)
            print('Else loop ', name)
            break

        break
    print(sum_width)

Это фактический вывод, который я получаю -

If loop total width -  7.0
If loop  [7.0]
7.0
If loop total width -  12.0
If loop  [7.0, 5.0]
12.0
If loop total width -  16.0
If loop  [7.0, 5.0, 4.0]
16.0
If loop total width -  23.0
If loop  [7.0, 5.0, 4.0, 7.0]
23.0

Я ожидаю получить два кластера вроде - [7.0, 5.0, 4.0] [7.0, 2.88888889]

1 Ответ

0 голосов
/ 03 июня 2019

В настоящее время ваш код будет добавлять ширину в список name независимо от того, является ли условие (end_x[i]>=start_x[j+1]) истинным или ложным.Затем он напрямую выходит из второго цикла, делая его избыточным.

Необходимо внести некоторые изменения:

  1. Вам нужно всего лишь сделать один проход через end_x иstart_x списки.Таким образом, необходим только один цикл for.
  2. Вам нужно будет отслеживать отдельный список для каждого кластера.
start_x = [ 8., 15., 20., 36., 40.]
end_x = [15., 20., 24., 43., 42.88888889]
width = [7., 5., 4., 7., 2.88888889]

sum_width = 0
clusters = [[width[0]]]     # initialise with first width

for i in range(1, len(end_x)):
    print(f'iter {i}: (start={start_x[i]}, end={end_x[i]}); width {width[i]}')

    if end_x[i-1] < start_x[i]:
        print(f'  doing a reset ({end_x[i-1]} < {start_x[i]})')
        sum_width = 0
        clusters.append([])

    sum_width += width[i]
    print('  total width:', sum_width)
    clusters[-1].append(width[i])  # append width into last cluster

print(clusters)
# [[7.0, 5.0, 4.0], [7.0, 2.88888889]]

Здесь мы переходим от второго элемента кконец списка, сравнивая предыдущий элемент end_x с текущим элементом start_x и создайте новый кластер, если значения не перекрываются.

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