【问题标题】:Plot multiple values with matplotlib without loop使用 matplotlib 绘制多个值而无需循环
【发布时间】:2018-10-30 17:40:08
【问题描述】:

我有两个嵌套列表,其中包含我想在同一个图中绘制的 x 轴和 y 轴的值。

使用 for 循环遍历值会产生预期的情节,但对于大型列表来说相对较慢。所以我一直在寻找相同的功能,但没有循环,我认为 matplotlib 可以处理,但情节不是我所期望的。

代码如下:

import matplotlib.pyplot as plt
xs = [[11, 20], [31, 31], [32, 33]]
ys = [[1, 10], [3, 4], [6, 10]]

用循环图就OK了:

fig, ax = plt.subplots()
for i, x in enumerate(xs):
    ax.plot(x, ys[i])
plt.show()

但只是将列表提供给 matplotlib,并不会生成相同的图:

fig, ax = plt.subplots()
ax.plot(xs, ys)
plt.show()

在没有循环的情况下执行此操作的正确方法是什么?

【问题讨论】:

    标签: python-3.x matplotlib


    【解决方案1】:

    当线段列表很大时,可以通过使用LineCollection而不是多次调用plt.plot来提高性能:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.collections as mcoll
    
    xs = [[11, 20], [31, 31], [32, 33]]
    ys = [[1, 10], [3, 4], [6, 10]]
    fig, ax = plt.subplots()
    
    # https://matplotlib.org/gallery/color/color_cycle_default.html
    prop_cycle = plt.rcParams['axes.prop_cycle']
    colors = prop_cycle.by_key()['color']
    segments = np.array(list(zip(xs, ys))).swapaxes(1,2)
    line_segments = mcoll.LineCollection(segments, colors=colors)
    ax.add_collection(line_segments)
    ax.set(xlim=(10,34), ylim=(0,11))
    plt.show()
    

    以下是一些使用LineCollection 的其他示例:


    LineCollection 期望第一个参数是[(pt0, pt1), (pt2, pt3), (pt4, pt5), ...] 形式的序列,其中每个pt 的形式为(x-coord, y-coord)。 Matplotlib 然后将这个LineCollection 渲染为线段

    pt0 --> pt1 
    pt2 --> pt3
    pt4 --> pt5
    etc.
    

    之所以在上面的代码中使用swapaxes是因为zip(xs, ys) 创建 ((x0, x1), (y0, y1)) 形式的对,而 LineCollection 希望点对的形式为 ((x0, y0), (x1, y1))

    【讨论】:

    • 听起来不错。以前没有听说过LineCollection,但它肯定更有效率。我注意到的一件事是您必须明确设置 xlim/ylim,否则该数字仅显示为 0:1 左右。这是真的吗?
    • 是的,这是真的。与高级绘图功能(例如plt.plotplt.scatterplt.imshow 等)不同,mcoll.LineCollection 是低级艺术家。它直接添加到坐标区ax,但不会更改坐标区的 xlim 和 ylim。所以你必须自己设置它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 2021-05-25
    相关资源
    最近更新 更多