使用 Itertools 和 For 循环创建水平条 (Python)

Posted

技术标签:

【中文标题】使用 Itertools 和 For 循环创建水平条 (Python)【英文标题】:Creating Horizontal Bars with Itertools and For Loops (Python) 【发布时间】:2021-01-28 23:42:38 【问题描述】:

我一直在使用 Matplotlib,并使用以下算法创建了一个水平条(本文底部提供了完整的代码和垃圾数据)。

# Version 1
ax.broken_barh([(depth_start[0], thick[0]), (depth_start[1], thick[1]), (depth_start[2], thick[2])], (25, 0.8),
               facecolors=('tab:brown', 'tab:blue', 'tab:green'))

产生以下图形输出:

所以我一直试图通过引入itertools 来提高代码效率

我设法将上述代码简化为版本 2:

# Version 2
for i in thick:
    ax.broken_barh([(next(cycle_depth), next(cycle_thick))], (15, 0.8), facecolors=(next(cycle_colour)))

太好了,这也会以相同的顺序以相同的颜色生成上面的条形图。

问题

但我正在努力实现我的下一个目标,即将facecolors=('tab:brown', 'tab:blue', 'tab:green') 替换为使用for loopfunction。此功能理想地根据粗细为每个条形选择正确的颜色。由于函数不断返回与 else 语句关联的值,所有 3 个条形都返回棕色(见下图)。

我尝试用 next(cycle_thick) 代替函数中的变量 cycle_think,但后来只有一种颜色再次正确。

colour_checker() 函数如下:

def colour_checker():
    if cycle_thick == 10:
        return 'tab:green'
    elif cycle_thick == 20:
        return 'tab:blue'
    else:
        return 'tab:brown'

# Version 3
for i in thick:
    ax.broken_barh([(next(cycle_depth), next(cycle_thick))], (10, 0.8), facecolors=colour_checker())

欢迎任何提示或建议!

完整代码和垃圾数据

import itertools
import matplotlib.pyplot as plt

# Junk data in the form of lists
depth_start = [90, 70, 40]  # top of lithology
thick = [30, 20, 10]  # thickness for each lithology
colour = ('tab:brown', 'tab:blue', 'tab:green')

# Lists to be cycled through
cycle_colour = itertools.cycle(colour)
cycle_depth = itertools.cycle(depth_start)
cycle_thick = itertools.cycle(thick)

#setting up the plot
fig, ax = plt.subplots()

def colour_checker():
    if cycle_thick == [0]:
        return 'tab:green'
    elif cycle_thick == [1]:
        return 'tab:blue'
    else:
        return 'tab:brown'


# Version 1
ax.broken_barh([(depth_start[0], thick[0]), (depth_start[1], thick[1]), (depth_start[2], thick[2])], (25, 0.8),
               facecolors=('tab:brown', 'tab:blue', 'tab:green'))

# Version 2
for i in thick:
    ax.broken_barh([(next(cycle_depth), next(cycle_thick))], (15, 0.8), facecolors=(next(cycle_colour)))

# Version 3
for i in thick:
    ax.broken_barh([(next(cycle_depth), next(cycle_thick))], (10, 0.8), facecolors=colour_checker())

ax.set_ylabel('X_UTM Position')
ax.set_xlabel('MAMSL')

plt.show()

【问题讨论】:

您坚持使用循环仪吗?任务也不完全清楚。您想在条形图中组合三个列表中的每个索引元素吗?无论其他两个列表生成为条形,您是否要循环显示三种颜色?如果条形图具有特定长度(例如,10 是绿色),您是否想要特定颜色?您的问题的所有三种解释都是可能的,并且处理方式不同。 您好,T 先生,感谢您的反馈,感谢您抽出宝贵时间解决我的困惑问题。我必须努力使我的问题变得清晰。是的,我的目标是为特定长度的 barh 分配特定的颜色。我没有必要使用循环。很像您使用 zip() 函数的方式。将使用更多。 唷。我担心你实际上想要第四个不同的版本。很高兴这解决了。 zip 确实是摆脱笨拙的索引任务的绝佳工具。尽情探索 matplotlib。 【参考方案1】:

由于结果的意图不明确,我为我能想象的所有三个版本都创建了示例。

import matplotlib.pyplot as plt

# Junk data in the form of lists
depth_start = [90, 70, 40, 200, 170, 140]  # top of lithology
thick = [30, 20, 10, 20, 10, 30]  # thickness for each lithology
colour = ('tab:brown', 'tab:blue', 'tab:green')

#setting up the plot
fig, ax = plt.subplots()

#Version 1: using zip to chain all three lists
for start, length, color in zip(depth_start, thick, colour+colour[::-1]):
    ax.broken_barh([(start, length)], (-0.4, 0.8), facecolors=color)
    
#Version 2: color cycler repetitive color assignments 
from itertools import cycle
cycle_colour = cycle(colour)

for start, length in zip(depth_start, thick):
    ax.broken_barh([(start, length)], (0.6, 0.8), facecolors=next(cycle_colour))
    
#Version 3: lookup table to color bars of a specific length with a certain color
color_dic = 30: 'tab:brown', 20: 'tab:blue', 10: 'tab:green'

for start, length in zip(depth_start, thick):
    ax.broken_barh([(start, length)], (1.6, 0.8), facecolors=color_dic[length])

ax.set_yticks(range(3)) 
ax.set_yticklabels(["Version 1", "Version 2", "Version 3"])   

plt.show()

示例输出:

【讨论】:

以上是关于使用 Itertools 和 For 循环创建水平条 (Python)的主要内容,如果未能解决你的问题,请参考以下文章

使用单个“for”循环或使用“itertools”库来反转字典

Python for 循环偏移 (Itertools.product)

python 在itertools中使用product方法来避免嵌套for循环

Itertools 等效于嵌套循环“for x in xs: for y in ys...”

python每日一类:itertools模块

用itertools.product简化嵌套for循环