如果我具有以下绘制例程,该例程绘制散点图和相应的线性回归并结合了图例手柄:
import pandas as pd
from scipy.stats import linregress
import numpy as np
import matplotlib.pyplot as plt
#data and Regression
x = np.arange(0,5,1)
y = np.arange(0,10,2)
df = pd.DataFrame(data = {'x':x,'y':y})
s, intcpt, r, p, serr = linregress(df.x, df.y)
xHat = np.linspace(0,5,100)
# do the plotting
fig,ax = plt.subplots()
df.plot(x='x',y='y',ax=ax,label='series1',ls=' ',marker='x',c='blue')
ls_handle, = ax.plot(xHat, s*xHat + intcpt, linestyle='-', marker=None, c='blue')
handle2merge = [ls_handle]
handles, labels = ax.get_legend_handles_labels()
handle_combined = zip(handles, handle2merge)
ax.legend(handle_combined, labels)
返回标记和线手柄合并的位置,如下所示:
现在,我想以类似的方式绘制另一个数据集:
#get current axis handles and labels
handle_start, label_start = ax.get_legend_handles_labels()
#second dataset and regression
x1 = np.arange(0,5,1)
y1 = np.arange(0,2.5,0.5)
df1 = pd.DataFrame(data = {'x':x1,'y':y1})
s1, intcpt1, r1, p1, serr1 = linregress(df1.x, df1.y)
xHat1 = np.linspace(0,5,100)
#plot second data set on same figure
marker_handle2, = ax.plot(df1.x, df1.y, marker = 'x', zorder=10,c='k', linestyle=' ')
line_handle2, = ax.plot(xHat, s1*xHat1 + intcpt1, linestyle='--', marker=None, c='k')
new_line_handles = [line_handle2]
new_marker_handles= [marker_handle2]
ax.legend(handle_start + zip(new_marker_handles,new_line_handles), label_start + ['series2'])
这将返回一个图,其中series1
图例句柄的句柄仅包含标记。
当我用len(handle_start)=1
构造手柄时,为什么handle_combined = zip(handles, handle2merge)
是这样?
答案 0 :(得分:1)
我已经在代码中稍加戳了一下。您正在做的是将list
中的tuples
传递到ax.legend
,这显然将每个tuple
中的每个Artist都作为图例中的一个条目。我实际上从未遇到过这种行为;可能是错误,也可能是ax.legend
的意外使用。
尽管如此,我认为在这种情况下,由于您事先知道行的外观,因此不必通过zip
和其他东西来回旋,您可以将自定义Line2D
传递给直接legend
:
import numpy as np
from scipy.stats import linregress
from matplotlib import pyplot as plt
from matplotlib import lines
x1 = np.arange(0, 5, 1)
y1 = np.arange(0, 10, 2)
x2 = np.arange(0, 5, 1)
y2 = np.arange(0, 2.5, 0.5)
m1, c1, r1, p1, serr1 = linregress(x1, y1)
m2, c2, r2, p2, serr2 = linregress(x2, y2)
x_pred = np.linspace(0,5,100)
fig, ax = plt.subplots()
first_line, = ax.plot(x_pred, x_pred * m1 + c1, ls='-', c='blue')
first_scatter = ax.scatter(x1, y1, marker='x', c='blue')
second_line, = ax.plot(x_pred, x_pred * m2 + c2, ls='--', c='black')
second_scatter = ax.scatter(x2, y2, marker='x', c='black')
ax.legend([lines.Line2D([0], [0], marker='x', ls='-', c='blue'),
lines.Line2D([0], [0], marker='x', ls='--', c='black')],
['series_1', 'series_2'])
我稍微整理了一下代码,但是可以随意接受最后一行和必要的导入。
答案 1 :(得分:0)
在最后一行中,仅使用已创建的合并句柄handle_combined
而不是handle_start
。
ax.legend(handle_combined + list(zip(new_marker_handles,new_line_handles)),
label_start + ['series2'])
长度为1,但是如果您查看列表的内容,则它是一个由两个对象组成的元组。如果打印handle_combined
,则会得到两个Line2D
对象的列表,其中一个是标记,另一个是行。
print (handle_combined)
# [(<matplotlib.lines.Line2D object at xxxxxxxxx>, <matplotlib.lines.Line2D object at xxxxxxxxx>)]
但是,如果您打印handle_start
,它只会返回一个Line2D
对象
print (handle_start)
# [<matplotlib.lines.Line2D object at xxxxxxxxx>]