2017-09-14 45 views
2

我有一个情节,其中每行是由变量a的值的彩色和由变量b的值具有线型:Matplotlib:颜色和由两个不同的变量线型带独立传说

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() 

enter image description here

现在我想分别为颜色和线条样式,所以一个框的标题为a和两个彩色线条的值为0.1,0.4,另一个框的标题为b,两条线条的线条的值分别为0.5和0.8。

也可以只有一个盒子,但用一些空格分开颜色和线条样式。

回答

3

你可以做这样的事情

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() 

的基本思路是,通过调用plt.legend()axes.add_artist()而不是仅仅调用plt.legend()`添加您自己的传奇。这使您可以根据需要添加尽可能多的图例。现在,您只需选择与每个图形关联的行,并为每个图例中的每个条目设置标题。

要创建不同风格的黑色图例,我们必须添加“虚拟”线条,其中不包含单个点(因此它们在图本身中不可见,但可以在图例中引用以更改颜色)。这工作,但似乎是一个古怪的黑客。对于小例子,这将毫无问题地工作,但对于大型项目来说,这不是最佳解决方案;所以如果有人知道这个更好的解决方案,请告诉我!

这造成该地块

+0

谢谢:)是否有可能改变在B传说黑色线条的颜色? – needRhelp

+0

@needRhelp看我的编辑。 – FlashTek

1

我找到了一个更简单的方法来做到这一点使用ggplot(使用默认的颜色)。

import pandas as pd 
import numpy as np 
from ggplot import * 

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"] 

# convert a and b to categorical variables 
df["a"] = df["a"].astype('category') 
df["b"] = df["b"].astype('category') 

ggplot(df, aes("x", "y", color = "a", linetype = "b")) + geom_line() + theme_bw() 

诀窍是将a和b转换为分类变量。然后ggplot自动添加两个图例。

enter image description here

相关问题