当前位置: 首页 > 知识库问答 >
问题:

如何为彩色线条创建基本图例?

袁博
2023-03-14

我目前正在完成一个更大的项目,最后一部分是在多色线的情节中添加一个简单的传说。该行只包含两种不同的颜色。

该图显示了地球和火星之间的距离随时间的变化。从3月到8月,这条线是橙色的,其他月份是蓝色的。图例应位于绘图右上角的一个简单框中,显示所用颜色的标签。像这样的东西会很好。

绘图数据来自一个巨大的矩阵,我称之为master\u array。在显示该问题涉及的绘图之前,它包含了一些任务所需的更多信息。对于我正在努力绘制的图来说,重要的是第0、1和6列,其中包含日期、相关日期行星之间的距离,在第6列中,我设置了一个标志,以确定给定点是否属于“三月到八月”集合(0表示九月到二月/“冬季”;1表示三月到八月/“夏季”)。master\u数组是一个numpy数组,数据类型为float64。它包含大约45k个数据点。

它看起来像:

In [3]: master_array
Out[3]: 
array([[ 1.89301010e+07,  1.23451036e+00, -8.10000000e+00, ...,
         1.00000000e+00,  1.00000000e+00,  1.89300000e+03],
       [ 1.89301020e+07,  1.24314818e+00, -8.50000000e+00, ...,
         2.00000000e+00,  1.00000000e+00,  1.89300000e+03],
       [ 1.89301030e+07,  1.25179997e+00, -9.70000000e+00, ...,
         3.00000000e+00,  1.00000000e+00,  1.89300000e+03],
       ...,
       [ 2.01903100e+07,  1.84236878e+00,  7.90000000e+00, ...,
         1.00000000e+01,  3.00000000e+00,  2.01900000e+03],
       [ 2.01903110e+07,  1.85066892e+00,  5.50000000e+00, ...,
         1.10000000e+01,  3.00000000e+00,  2.01900000e+03],
       [ 2.01903120e+07,  1.85894904e+00,  9.40000000e+00, ...,
         1.20000000e+01,  3.00000000e+00,  2.01900000e+03]])

这是获取我在开头描述的绘图的函数:

def md_plot3(dt64=np.array, md=np.array, swFilter=np.array):
    """ noch nicht fertig """
    y, m, d = dt64.astype(int) // np.c_[[10000, 100, 1]] % np.c_[[10000, 100, 100]]
    dt64 = y.astype('U4').astype('M8') + (m-1).astype('m8[M]') + (d-1).astype('m8[D]')

    cmap = ListedColormap(['b','darkorange'])

    plt.figure('zeitlich-global betrachtet')
    plt.title("Marsdistanz unter Berücksichtigung der Halbjahre der steigenden und sinkenden Temperaturen",
              loc='left', wrap=True)
    plt.xlabel("Zeit in Jahren\n")
    plt.xticks(rotation = 45)
    plt.ylabel("Marsdistanz in AE\n(1 AE = 149.597.870,7 km)")
#    plt.legend(loc='upper right', frameon=True) # worked formerly
    ax=plt.gca()
    plt.style.use('seaborn-whitegrid')

#convert dates to numbers first
    inxval = mdates.date2num(dt64)
    points = np.array([inxval, md]).T.reshape(-1,1,2)
    segments = np.concatenate([points[:-1],points[1:]], axis=1)

    lc = LineCollection(segments, cmap=cmap, linewidth=3)
# set color to s/w values
    lc.set_array(swFilter)
    ax.add_collection(lc)

    loc = mdates.AutoDateLocator()
    ax.xaxis.set_major_locator(loc)
    ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))

    ax.autoscale_view()

在更大的脚本中还有另一个函数(散点图)来标记曲线的最小值和最大值,但我想这在这里并不重要。

我已经试过了,结果出现了一个图例,上面显示了一个垂直的颜色条,只有一个标签,还有这个问题的答案中描述的两个选项,因为它看起来更像我的目标,但无法使它适用于我的案例。

也许我应该补充说,我只是一个初学者在python,这是我的第一个项目,所以我不熟悉更深层次的html" target="_blank">功能matplotlib可能是什么原因,我不能定制提到的答案得到它在我的情况下工作。

更新

import matplotlib.dates as mdates
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap
from matplotlib.lines import Line2D

def md_plot4(dt64=np.array, md=np.array, swFilter=np.array):
    y, m, d = dt64.astype(int) // np.c_[[10000, 100, 1]] % np.c_[[10000, 100, 100]]
    dt64 = y.astype('U4').astype('M8') + (m-1).astype('m8[M]') + (d-1).astype('m8[D]')

    z = np.unique(swFilter)

    cmap = ListedColormap(['b','darkorange'])

    fig = plt.figure('Test')
    plt.title("Test", loc='left', wrap=True)
    plt.xlabel("Zeit in Jahren\n")
    plt.xticks(rotation = 45)
    plt.ylabel("Marsdistanz in AE\n(1 AE = 149.597.870,7 km)")
#    plt.legend(loc='upper right', frameon=True) # worked formerly
    ax=plt.gca()
    plt.style.use('seaborn-whitegrid')
    #plt.style.use('classic')

#convert dates to numbers first
    inxval = mdates.date2num(dt64)
    points = np.array([inxval, md]).T.reshape(-1,1,2)
    segments = np.concatenate([points[:-1],points[1:]], axis=1)

    lc = LineCollection(segments, array=z, cmap=plt.cm.get_cmap(cmap), 
                        linewidth=3)
# set color to s/w values
    lc.set_array(swFilter)
    ax.add_collection(lc)
    fig.colorbar(lc)


    loc = mdates.AutoDateLocator()
    ax.xaxis.set_major_locator(loc)
    ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))

    ax.autoscale_view()

    def make_proxy(zvalue, scalar_mappable, **kwargs):
        color = scalar_mappable.cmap(scalar_mappable.norm(zvalue))
        return Line2D([0, 1], [0, 1], color=color, **kwargs)
    proxies = [make_proxy(item, lc, linewidth=2) for item in z]
    ax.legend(proxies, ['Winter', 'Summer'])


    plt.show()

md_plot4(dt64, md, swFilter)

它有什么好处:

它显示了一个图例,并根据标签显示了正确的颜色。

-还有什么需要优化:

1) 图例不在方框中,图例的“线”干扰了绘图的底层。正如用户重要性ceofbeingernest所述,这是由使用plt引起的。风格使用('seaborn-whitegrid')。因此,如果有一种方法可以使用plt。风格将('seaborn-whitegrid')plt的图例样式一起使用。风格使用('classic'),这可能会有所帮助。2) 更大的问题是色条。我在原始代码中添加了fig.colorbar(lc)行,以实现我根据这个答案寻找的结果。

所以我尝试了一些其他的改变:

我使用了plt。风格使用('classic')以我需要的方式获得一个图例,但这让我损失了plt的良好风格。风格如前所述,使用('seaborn-whitegrid')。此外,我根据前面提到的答案禁用了我之前添加的色条行。

这就是我得到的:

import matplotlib.dates as mdates
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap
from matplotlib.lines import Line2D

def md_plot4(dt64=np.array, md=np.array, swFilter=np.array):
    y, m, d = dt64.astype(int) // np.c_[[10000, 100, 1]] % np.c_[[10000, 100, 100]]
    dt64 = y.astype('U4').astype('M8') + (m-1).astype('m8[M]') + (d-1).astype('m8[D]')

    z = np.unique(swFilter)

    cmap = ListedColormap(['b','darkorange'])

    #fig =
    plt.figure('Test')
    plt.title("Test", loc='left', wrap=True)
    plt.xlabel("Zeit in Jahren\n")
    plt.xticks(rotation = 45)
    plt.ylabel("Marsdistanz in AE\n(1 AE = 149.597.870,7 km)")
#    plt.legend(loc='upper right', frameon=True) # worked formerly
    ax=plt.gca()
    #plt.style.use('seaborn-whitegrid')
    plt.style.use('classic')

#convert dates to numbers first
    inxval = mdates.date2num(dt64)
    points = np.array([inxval, md]).T.reshape(-1,1,2)
    segments = np.concatenate([points[:-1],points[1:]], axis=1)

    lc = LineCollection(segments, array=z, cmap=plt.cm.get_cmap(cmap), 
                        linewidth=3)
# set color to s/w values
    lc.set_array(swFilter)
    ax.add_collection(lc)
    #fig.colorbar(lc)


    loc = mdates.AutoDateLocator()
    ax.xaxis.set_major_locator(loc)
    ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))

    ax.autoscale_view()

    def make_proxy(zvalue, scalar_mappable, **kwargs):
        color = scalar_mappable.cmap(scalar_mappable.norm(zvalue))
        return Line2D([0, 1], [0, 1], color=color, **kwargs)
    proxies = [make_proxy(item, lc, linewidth=2) for item in z]
    ax.legend(proxies, ['Winter', 'Summer'])


    plt.show()

md_plot4(dt64, md, swFilter)

它有什么好处:

它以我需要的方式展示了传奇。

它不再显示颜色条了。

-要优化的是什么:

情节不再五彩缤纷了。

这也不是传说。

classic风格不是我之前解释过的我想要的。。。

因此,如果有人有好的建议,请让我知道!

我使用的是numpy版本1.16。2和matplotlib版本3.0。3.

共有2个答案

郗阳德
2023-03-14

因此,以下是如何为多色线条创建基本图例的答案,该图例包含每种使用颜色的多个标签,并且在绘图旁边不显示颜色栏(标准颜色栏,图例内无任何内容;有关问题的更多信息,请参阅原始问题的更新):

多亏了许多有用的注释,我想出了在LineCollection()中添加一个norm的方法,通过禁用fig.colorbar()(也请参见此)在移除颜色条时避免以单色线结束。要添加的附加参数(在本例中为“norm”)是norm=plt。Normalize(z.min(),z.max()),其中z是一个数组,其中包含负责段的不同颜色的信息。请注意,z只需要为每种不同的颜色保存一个元素。这就是为什么我将我的swFilter数组包装到np中,该数组由每个数据点一个标志组成。unique()

在不接触plt的方框内获得正确的图例。风格使用(),我只需将正确的参数添加到ax。图例()。在我的例子中,一个简单的frameon=True完成了这项工作。

下面是代码:

import matplotlib.dates as mdates
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap
from matplotlib.lines import Line2D

def md_plot4(dt64=np.array, md=np.array, swFilter=np.array):
    y, m, d = dt64.astype(int) // np.c_[[10000, 100, 1]] % np.c_[[10000, 100, 100]]
    dt64 = y.astype('U4').astype('M8') + (m-1).astype('m8[M]') + (d-1).astype('m8[D]')

    z = np.unique(swFilter)

    cmap = ListedColormap(['b','darkorange'])

    #fig =
    plt.figure('Test')
    plt.title("Marsdistanz unter Berücksichtigung der Halbjahre der steigenden und sinkenden Temperaturen\n",
              loc='left', wrap=True)
    plt.xlabel("Zeit in Jahren\n")
    plt.xticks(rotation = 45)
    plt.ylabel("Marsdistanz in AE\n(1 AE = 149.597.870,7 km)")
    plt.tight_layout()
    ax=plt.gca()
    plt.style.use('seaborn-whitegrid')

#convert dates to numbers first
    inxval = mdates.date2num(dt64)
    points = np.array([inxval, md]).T.reshape(-1,1,2)
    segments = np.concatenate([points[:-1],points[1:]], axis=1)

    lc = LineCollection(segments, array=z, cmap=plt.cm.get_cmap(cmap),
                        linewidth=3, norm=plt.Normalize(z.min(), z.max()))
# set color to s/w values
    lc.set_array(swFilter)
    ax.add_collection(lc)

    loc = mdates.AutoDateLocator()
    ax.xaxis.set_major_locator(loc)
    ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))

    ax.autoscale_view()

    def make_proxy(zvalue, scalar_mappable, **kwargs):
        color = scalar_mappable.cmap(scalar_mappable.norm(zvalue))
        return Line2D([0, 1], [0, 1], color=color, **kwargs)
    proxies = [make_proxy(item, lc, linewidth=2) for item in z]
    ax.legend(proxies, ['Halbjahr der sinkenden \nTemperaturen',
                        'Halbjahr der steigenden \nTemperaturen'], frameon=True)

    plt.show()

md_plot4(dt64, md, swFilter)

请注意,我添加了plt.tight_layout(),以确保在窗口模式下显示情节的标题和轴的描述没有任何截止。

现在的新问题(由于添加了tight_layout())是,尽管绘图右侧有很多可用空间(调用颜色条时会出现的位置),但绘图会得到水平压缩。

这需要另一个修复,但目前我不知道如何修复。因此,如果有人知道如何防止绘图标题和轴的描述在窗口模式下被切断,我将非常感谢您留下评论。

谷梁宝
2023-03-14

要在matplotlib中获得多色绘图,请标记绘图,然后调用legend()函数。下面的示例代码取自一个链接,但当链接断开时,文章如下。。

这里使用的图表是一条直线,但同样的原理也适用于其他图表类型,正如您从这个其他答案中所看到的

import matplotlib.pyplot as plt
import numpy as np

y = [2,4,6,8,10,12,14,16,18,20]
y2 = [10,11,12,13,14,15,16,17,18,19]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = numbers')
ax.plot(x, y2, label='$y2 = other numbers')
plt.title('Legend inside')
ax.legend()
plt.show()

此代码将显示以下图像(图表中有图例)

希望这能有所帮助

 类似资料:
  • 我有一个12列的矩阵,我使用中的函数来绘制boxplot。 使用以下命令: 我想要的是以红色、绿色和蓝色呈现前三个方框图。接下来的三件是黄色的,接下来的三件是橙色的,接下来的三件是紫色的。 我该怎么做呢? 非常感谢。

  • 我希望有条件地更改折线图的背景色。在给定的示例中,我希望修改图表,使任何具有Y值的部分 LineChartJavaFXTest。JAVA LineChart.css

  • 我试图理解DOM结构 所以我在正文中添加了 但我不明白为什么滚动条也被染成红色? null null

  • ANSI 例子 33-11. 一个 "彩色的"地址资料库 1 #!/bin/bash 2 # ex30a.sh: ex30.sh的"彩色" 版本. 3 # 没有加工处理的地址资料库 4 5 6 clear # 清除屏幕. 7 8 echo -n "

  • 我试图为数据集创建多水平条形图。这些数据涉及跑步比赛的比赛时间。 Dataframe有以下列:名称、年龄组、完成时间、完成地点、家乡。下面是示例数据。 我想创建一个类似下图的条形图。每个年龄组将有一个条形图,最快的跑步者在图表的底部,跑步者的名字与城市和次数跑了比赛低于他们的名字。 我需要一个for循环还是一个简单的groupby工作?每个年龄组的数量和大小可以根据种族动态变化,因此它不是一个常数

  • 主要内容:将彩色图像转换为灰度在前面的章节中,我们讨论了如何读取不同类型的输入图像(二进制,灰度,BGR等)。 在本章中,我们将学习如何将一种图像转换为另一种图像。 包中名为的类提供了将图像从一种颜色转换为另一种颜色的方法。 将彩色图像转换为灰度 使用方法将彩色图像转换为灰度。 以下是此方法的语法。 该方法接受以下参数 - src - 表示来源的矩阵。 dst - 表示目的地的矩阵。 code - 表示转换类型的整数代码,例如