Как полностью распределить проценты, чтобы установить диапазон в python? - PullRequest
4 голосов
/ 16 января 2020

Я знаю, что заголовок звучит странно, поэтому я объясню, чего я пытаюсь достичь здесь:

РЕДАКТИРОВАТЬ: Пример кода , должно складываться до 24, но не

У меня есть 10 источников данных, которые все складываются в мой 11-й источник данных. My data Я хочу отобразить эти данные на кольце 24 RGB, поэтому я конвертирую каждый источник данных в процент от общего числа. Data converted to percentage of total Однако, если я сейчас попытаюсь отобразить это на моем кольце светодиодов, умножив каждый процент на 24, например, 0,56x24, 0,14x24 и т. Д. c Я не всегда использую все светодиоды, иногда перебирая или ниже из-за округления в большую или меньшую сторону.

Итак, мой вопрос: есть ли функция, которая может равномерно и полностью распределять данные по 24 светодиодам?

Надеюсь, это объясняет то, что я Я пытаюсь достичь, но, пожалуйста, спросите, нужна ли вам дополнительная информация.

Спасибо

Ответы [ 2 ]

1 голос
/ 16 января 2020

Решение

Этот код сгенерирует «индекс цвета» для каждого из ваших светодиодов.

Вход (data) представляет собой список итогов из вашего источника данных:

# generate fake some data
# this should be coming from you
import random
data = [random.randint(500, 1000) for x in range(10)]

# compute the commutative sum of the entries
cumsum = [0,]
for i in range(len(data)):
    cumsum.append(cumsum[i]+data[i])
cumsum.pop(0)
total = cumsum[-1]

# now we are ready to set the LEDs' color index
led_count = 24
leds = [0] * led_count

item = 0
for i in range(len(leds)):
    while (i+1)/led_count > cumsum[item]/total:
        item += 1
    leds[i] = item

Например, если ваши итоги (в data) равны

[938, 765, 611, 980, 807, 961, 564, 919, 548, 888 ]

Тогда результаты в leds будут

[0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4 , 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9]

Значение светодиодов должно быть установлено на цвет 0 , что бы это ни было, затем следующие три до цвета 1 , и т. Д. c.

Как это работает?

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

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

Например, вместо того, чтобы сказать, у нас есть 10%, 20%, 60%, 10% каждой категории, мы рассматриваем текущий счет: 10%, 30%, 90%, 100%.

Каждый светодиод представляет 1/24% (для 24 светодиодов). При переходе через светодиоды (1/24%, 2/24%, 3/24%, 4/24%, ...) код проверяет, перешли ли мы порог от одной категории к другой, и сделали ли мы , увеличивает категорию, назначенную текущему индикатору.

Возможно, процент к категории настолько низок, что он будет полностью пропущен, но алгоритм даст вам максимально хорошее распределение.

Бонусные баллы

Поскольку в конечном итоге у вас будут значения RGB, есть возможность иметь «частичные» светодиоды.

Для этого вам необходимо отслеживать, где в Интервал между светодиодами является именно границей категории, и соответственно смешайте цвета.

Это не включено в код.

1 голос
/ 16 января 2020

Вы можете создать вафельную диаграмму и взять тот же счет. Какой бы алгоритм не использовал Waffle, он, вероятно, хорошо опробован.

Полный источник находится на github и не очень длинный. Используя тот же подход, мы получаем:

import matplotlib.pyplot as plt
from pywaffle import Waffle

num_leds = 24

values = [15812, 4162, 3054, 0, 43, 1564, 3080, 10, 320, 9]
labels = ['Black Coal', 'Brown Coal', 'Gas', 'Liquid Fuel', 'Other', 'Hydro', 'Wind', 'Large Solar', 'Small Solar', 'Battery']
colors = ['black', 'maroon', 'magenta', 'lightblue', 'red', 'mediumblue', 'coral', 'goldenrod', 'gold', 'blueviolet']

block_number_per_cat = [round(v * num_leds / sum(values)) for v in values]
blocks_per_label = {lab: num for lab, num in zip(labels, block_number_per_cat)}

print(blocks_per_label)

fig = plt.figure(
    FigureClass=Waffle,
    rows=1,
    columns=num_leds,
    values=values,
    labels=labels,
    colors=colors,
    icons='lightbulb',
    font_size=16,
    legend={'loc': 'upper right', 'bbox_to_anchor': (1, -0.1)}
)
plt.show()

Ответ:

{'Black Coal': 14, 'Brown Coal': 4, 'Gas': 3, 'Liquid Fuel': 0, 'Other': 0, 'Hydro': 1, 'Wind': 3, 'Large Solar': 0, 'Small Solar': 0, 'Battery': 0}

waffle plot

...