【问题标题】:How to distribute percentages completely to set range in python?如何完全分配百分比以在 python 中设置范围?
【发布时间】:2020-05-03 02:57:19
【问题描述】:

我知道标题听起来令人困惑,所以我将在这里解释我想要实现的目标:

编辑:Code example,加起来应该是 24 但不是

我有 10 个数据源,它们加起来就是我的第 11 个数据源。 我想在 24 RGB 环上显示这些数据,所以我将每个数据源转换为总数的百分比。 但是,如果我现在尝试通过将每个百分比乘以 24 来在我的 LED 环上显示它,例如0.56x24、0.14x24 等 我并不总是使用所有 LED,有时会因为向上或向下舍入而过度或不足。

所以我的问题是,是否有一个函数可以按数据均匀且完全地分布在 24 个 LED 上?

我希望这能解释我想要实现的目标,但请询问您是否需要更多信息。

谢谢

【问题讨论】:

  • 如果我正确理解了这个问题,一种有效的方法可能是使用累积值并一致地舍入(例如,总是向下)。如果您以文本/代码形式提供一些输入、当前输出和预期输出,最终提供minimal reproducible example,可能会使您的问题更加清晰。

标签: python percentage


【解决方案1】:

您可以创建一个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}

【讨论】:

  • 这在分发方面非常完美,但你知道我怎样才能从中获取原始数据吗?
【解决方案2】:

解决方案

此代码将为您的每个 LED 生成“颜色索引”。

输入 (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 值,因此可以选择使用“部分”LED。

为此,您需要跟踪 LED 间隔中的哪个位置恰好是类别边界,并相应地混合颜色。

这不包含在代码中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 2013-03-24
    • 2012-10-03
    • 1970-01-01
    • 2019-05-02
    相关资源
    最近更新 更多