如何将百分比完全分配到 python 中的设置范围?
How to distribute percentages completely to set range in python?
我知道标题听起来很混乱,所以我将在这里解释我想要实现的目标:
编辑:Code example,加起来应该是 24 但不是
我有 10 个数据源,它们加起来就是我的第 11 个数据源。
我想在 24 RGB 环上显示此数据,因此我将每个数据源转换为总数的百分比。
但是,如果我现在尝试通过将每个百分比乘以 24 来在我的 LED 环上显示它,例如0.56x24、0.14x24 等我并不总是使用所有的 LED,有时会由于向上或向下舍入而超过或低于。
所以我的问题是,是否有一种功能可以将数据均匀且完整地分布在24个LED上?
我希望这能解释我正在努力实现的目标,但请询问您是否需要更多信息。
谢谢
您可以创建一个 Waffle chart 并进行相同的计数。无论 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}
一个解决方案
此代码将为您的每个 LED 生成 "color index"。
输入 (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]
意味着 LED 的第一个应该设置为 color 0,无论如何,接下来的三个 color 1,等等.
这是如何工作的?
代码不是试图计算每个类别需要多少个 LED,而是计算分配给每个 LED 的类别。这保证了我们不会多,不会少于我们实际拥有的 LED 数量。
代码使用累积总和来跟踪从一个类别到下一个类别需要发生变化的位置。
例如我们不是说每个类别有 10%、20%、60%、10%,而是考虑一个 运行 计数:10%、30%、90%、100%。
每个 LED 代表 1/24%(24 个 LED)。当穿过 LED(1/24%、2/24%、3/24%、4/24%、...)时,代码会检查我们是否从一个类别越过阈值到下一个类别,如果我们做到了, 递增分配给当前 LED 的类别。
有可能某个类别的百分比太低,以至于会被完全跳过,但算法会为您提供尽可能好的分布。
奖励积分
由于最终您将获得 RGB 值,因此可以选择 "partial" 个 LED。
为此,您需要跟踪 LED 间隔中恰好是类别边界的位置,并相应地混合颜色。
这不包含在代码中。
我知道标题听起来很混乱,所以我将在这里解释我想要实现的目标:
编辑:Code example,加起来应该是 24 但不是
我有 10 个数据源,它们加起来就是我的第 11 个数据源。
所以我的问题是,是否有一种功能可以将数据均匀且完整地分布在24个LED上?
我希望这能解释我正在努力实现的目标,但请询问您是否需要更多信息。
谢谢
您可以创建一个 Waffle chart 并进行相同的计数。无论 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}
一个解决方案
此代码将为您的每个 LED 生成 "color index"。
输入 (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]
意味着 LED 的第一个应该设置为 color 0,无论如何,接下来的三个 color 1,等等.
这是如何工作的?
代码不是试图计算每个类别需要多少个 LED,而是计算分配给每个 LED 的类别。这保证了我们不会多,不会少于我们实际拥有的 LED 数量。
代码使用累积总和来跟踪从一个类别到下一个类别需要发生变化的位置。
例如我们不是说每个类别有 10%、20%、60%、10%,而是考虑一个 运行 计数:10%、30%、90%、100%。
每个 LED 代表 1/24%(24 个 LED)。当穿过 LED(1/24%、2/24%、3/24%、4/24%、...)时,代码会检查我们是否从一个类别越过阈值到下一个类别,如果我们做到了, 递增分配给当前 LED 的类别。
有可能某个类别的百分比太低,以至于会被完全跳过,但算法会为您提供尽可能好的分布。
奖励积分
由于最终您将获得 RGB 值,因此可以选择 "partial" 个 LED。
为此,您需要跟踪 LED 间隔中恰好是类别边界的位置,并相应地混合颜色。
这不包含在代码中。