Matplotlib:颜色和线条样式由两个带有单独图例的不同变量组成

nee*_*elp 5 python matplotlib legend

我有一个绘图,其中每条线都由变量a的值着色,而线型由变量b的值:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# some data
x = np.array([[1, 2, 0.1, 0.5], [2, 3, 0.1, 0.5], 
              [1, 4, 0.4, 0.8], [2, 1, 0.4, 0.8],
              [1, 1, 0.1, 0.8], [2, 3, 0.1, 0.8], 
              [1, 3, 0.4, 0.5], [2, 3, 0.4, 0.5]])
df = pd.DataFrame(x)
df.columns = ["x", "y", "a", "b"]
df.head()

# define color scheme and line style
colors = ["C1", "C2", "C3"]
linestyles = ['-', "--", ":"]


for a_idx, a in enumerate(np.unique(df["a"])):
    for b_idx, b in enumerate(np.unique(df["b"])):
        df2 = df[df["a"] == a]
        df2 = df2[df2["b"] == b]
        plt.plot(df2["x"], df2["y"], c = colors[a_idx], ls = linestyles[b_idx])
plt.legend(['a = 0.1, b = 0.5', 'a = 0.1, b = 0.8', 
            'a = 0.4, b = 0.5', 'a = 0.4, b = 0.8'])
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

现在,我想对颜色和线型使用单独的图例,因此,一个带有标题a的框和两个值为0.1、0.4的彩色线,另一个带有标题b的框以及两个具有不同线型的值为0.5和0.8的线。

也可以只具有一个框,但将颜色和线型分开一定的空间。

zim*_*rol 5

你可以做这样的事情

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


# some data
x = np.array([[1, 2, 0.1, 0.5], [2, 3, 0.1, 0.5], 
              [1, 4, 0.4, 0.8], [2, 1, 0.4, 0.8],
              [1, 1, 0.1, 0.8], [2, 3, 0.1, 0.8], 
              [1, 3, 0.4, 0.5], [2, 3, 0.4, 0.5]])
df = pd.DataFrame(x)
df.columns = ["x", "y", "a", "b"]
df.head()

# define color scheme and line style
colors = ["C1", "C2", "C3"]
linestyles = ['-', "--", ":"]

fig, axes = plt.subplots()

for a_idx, a in enumerate(np.unique(df["a"])):
    for b_idx, b in enumerate(np.unique(df["b"])):
        df2 = df[df["a"] == a]
        df2 = df2[df2["b"] == b]
        axes.plot(df2["x"], df2["y"], c = colors[a_idx], ls = linestyles[b_idx])

#dummy lines with NO entries, just to create the black style legend
dummy_lines = []
for b_idx, b in enumerate(np.unique(df["b"])):
    dummy_lines.append(axes.plot([],[], c="black", ls = linestyles[b_idx])[0])
lines = axes.get_lines()
legend1 = plt.legend([lines[i] for i in [0,2]], ["a = 0.1", "a = 0.4"], loc=1)
legend2 = plt.legend([dummy_lines[i] for i in [0,1]], ["b = 0.5", "b = 0.8"], loc=4)
axes.add_artist(legend1)

plt.show()
Run Code Online (Sandbox Code Playgroud)

基本思想是,您可以通过调用plt.legend()axes.add_artist()不是仅调用plt.legend()` 添加自己的图例。这使您可以根据需要添加任意多个图例。现在,您只需选择与每个图解相关的线,并为每个图例中的每个条目设置标题。

要为不同样式创建黑色图例,我们必须添加“虚拟”线,该线不包含单个点(因此它们在图本身中不可见,但可以在图例中引用以更改颜色)。这是可行的,但似乎是个古怪的技巧。对于较小的示例,这将毫无问题地起作用,但是对于大型项目,这不是最佳解决方案。因此,如果有人知道更好的解决方案,请告诉我!

这创建了这个情节