【问题标题】:Convert a list of 3-Tuples in to list of list for a matplot stacked bar chart将 3 元组列表转换为 matplot 堆积条形图的列表列表
【发布时间】:2020-05-23 03:13:41
【问题描述】:

我有一个包含 3 个元组的装箱问题解决方案的列表,如下所示:

sorted_sol = [(0, 1, 170), (1, 1, 250), (2, 1, 250), (3, 1, 62), (3, 2, 30), (4, 1, 62), (4, 3, 62), (5, 2, 122), (6, 1, 212)]

例如,第一个 3-Tuple 表示从长度 0 到 1 @ 170

我正在尝试将 3-Tuples 列表转换为 matplot 堆积条形图的列表列表,但我正在努力处理循环逻辑。结果应该是。

import matplotlib.pyplot as plt
import numpy as np
bars = list(set([int(i[0]) for i in sorted_sol]))
#loop logic here to end up with data
b1 = [170, 250, 250, 62, 62, 122, 212]
b2 = [0,   0,   0,   30, 62, 122, 0]
b3 = [0,   0,   0,   30, 62, 0,   0]
b4 = [0,   0,   0,   0,  62, 0,   0]
data =[b1, b2, b3, b4]
for c in range(0, 3):
    if c == 0:
        plt.bar(bars, data[c])
    else:
        plt.bar(bars, data[c], bottom=data[c-1])
plt.show()

此外,底部属性似乎对我不起作用,因为它似乎无法正确堆叠第 3 条和第 4 条。

【问题讨论】:

  • 鉴于您的元组列表,我不确定输出应该是什么样子。您能否提供有关如何正确处理数据的更多信息。
  • 请参阅下面来自 Quang Hoang 的帖子以了解所需的输出。仍在寻找循环逻辑从sorted_sol 到达data
  • 如果您将规则包含在问题中,则这些规则不清楚。您可能应该发布您想出的循环并解释为什么它有缺陷。它可能会让您更清楚如何将元组列表转换为四个 b 列表。
  • for s, (a, b, c) in enumerate(sorted_sol):print("From length " + str(a) + " cut " + str(b) + " @ " + str(c)) 从长度 0 切割 1 @ 170 从长度 1 切割 1 @ 250 从长度 2 切割 1 @ 250 从长度 3 切割 1 @ 62 从长度 3 切割 2 @ 30 从长度 4 切割1 @ 62 从长度 4 切割 3 @ 62 从长度 5 切割 2 @ 122 从长度 6 切割 1 @ 212 我想我遇到的最大问题是 len(sorted_sol) 是 9 而 len(b1) 或独特的库存长度是7 使循环逻辑对我来说很困难。 :) 我还应该指出,装箱问题的库存长度是 250
  • 您需要不同的“b”变量吗?还是直接去data 就够了?

标签: python matplotlib tuples bin-packing


【解决方案1】:

IIUC,这样的东西应该可以工作

dx = max(x[0] for x in sorted_sol) + 1
predata = []
for x in range(dx):
    col_data = [tup[1:] for tup in sorted_sol if tup[0] == x]
    temp = [n * [y] for n, y in col_data]
    predata.append([i for sublist in temp for i in sublist])

dy = max(len(x) for x in predata)
data = [[i.pop() if i else 0 for i in predata] for _ in range(dy)]

输出:

[[170, 250, 250, 30, 62, 122, 212],
 [0, 0, 0, 30, 62, 122, 0],
 [0, 0, 0, 62, 62, 0, 0],
 [0, 0, 0, 0, 62, 0, 0]]

您的绘图不起作用的原因是bottom 需要是数据的累积总和。尝试类似:

bottom = 7 * [0]
for i in range(4):
    plt.bar(range(7), data[c], bottom=bottom)
    bottom = [sum([a, b]) for a, b in zip(data[c], bottom)]

如果你使用numpy,最后一行的加法可以简单地是data[i] + bottom

【讨论】:

  • 感谢您的帮助,data 的输出是正确的。我仍在消化第一个代码块,但乍一看,您是否看到不必定义范围 dxdy 的方法。这些范围可能会根据用户输入等而有所不同。感谢您指出bottom 需要数据的累积总和,这是有道理的。
【解决方案2】:

我没有按照你的逻辑从sorted_sol 到列表b1,b2,b3,b4。我觉得这很奇怪,因为您的 sorted_sol 只有 362data 有 5 个这样的值。

无论如何,一旦您到达data,您可以考虑使用pandas 来实现堆叠条形功能:

import pandas as pd
df = pd.DataFrame(data).T
df.plot.bar(stacked=True)

输出:

【讨论】:

  • 谢谢,这在呈现数据方面是有效的。查看这些元组 (3, 1, 62), (4, 1, 62), (4, 3, 62) 意味着从长度 3 到 62 处切割 1,从长度 4 到 62 处切割 1 和从长度 4 处切割 3 处64.装箱解决方案来自PYTHON-MIP docs.python-mip.com/en/latest/examples.html《切割库存/一维装箱问题》。感谢您的帮助。
【解决方案3】:
  • sort 元组(索引一,索引零)上的列表
  • group 按索引列出的元组之一
  • 每个组将是一个b 列表
    • 元组索引 0 是(新)b 列表中的索引

我能看到的最好的,但似乎不适合元组列表和 b 列表

【讨论】:

  • 感谢您的帮助。 itertools 是我需要了解的更多内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 2012-06-05
  • 1970-01-01
  • 2022-09-27
  • 2016-09-28
  • 1970-01-01
相关资源
最近更新 更多