我想知道为什么取决于您在plt.plot()
上ax
拨打ax
的原因matplotlib
可能会或可能无法在下游进行修改。这是ax.plot
中的错误还是我误解了什么?说明问题的一个例子如下所示。
我正在尝试修改绘图函数调用下游的图例位置,类似于讨论的here。无论出于何种原因,这种接缝取决于我如何调用import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def myplot(df, ax, loop_cols):
if loop_cols:
for col in df.columns:
ax.plot(df.loc[:, col])
else:
ax.plot(df)
ax.legend(df.columns)
return ax
。以下是说明问题的两个例子
ax.plot()
这相当于在pd.Series
上反复拨打pd.DataFrame
,或在df = pd.DataFrame(np.random.randn(100, 3)).cumsum()
fig = plt.figure()
ax = fig.gca()
myplot(df, ax, loop_cols=True)
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()
上拨打一次。但是,根据调用的方式,它会导致无法稍后修改图例,如下所示。
fig = plt.figure()
ax = fig.gca()
myplot(df, ax, loop_cols=False)
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()
图表图例正确设置为右侧
matplotlib
图表图例未设置为适当的位置
这是2.1.0
版本df <- copy_to(sc, tibble(id=1:4, timestamp=c(
"2017-07-01 23:49:00.000", "2017-07-01 23:50:00.000",
# 6 minutes gap
"2017-07-01 23:56:00.000",
# 1 minute gap
"2017-07-01 23:58:00.000")
), "df", overwrite=TRUE)
min_max <- df %>%
summarise(min(unix_timestamp(timestamp)), max(unix_timestamp(timestamp))) %>%
collect() %>%
unlist()
答案 0 :(得分:0)
我不知道为什么会发生这种行为....但是你在函数中调用ax.legend
两次,一次调用它。更改函数,以便函数内部对ax.legend()
的调用包含所有信息,从而解决问题。这包括传递图例句柄和标签。在下面的示例中,我使用ax.lines
来获取Line2D
个对象,但是如果您的绘图更复杂,则可能需要使用lines = ax.plot()
如果图例的属性发生变化,那么您可以修改该函数以接受传递给ax.legend
的参数。
def myplot(df, ax, loop_cols):
if loop_cols:
for col in df.columns:
ax.plot(df.loc[:, col])
else:
ax.plot(df)
#ax.legend(df.columns) # modify this line
ax.legend(ax.lines, df.columns, loc='center left', bbox_to_anchor=(1, 0.5))
return ax
fig, (ax,ax2) = plt.subplots(1,2,figsize=(6,4))
df = pd.DataFrame(np.random.randn(100, 3)).cumsum()
myplot(df, ax, loop_cols=True)
ax.set_title("loop_cols=True")
#ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) # No need for this
myplot(df, ax2, loop_cols=False)
ax2.set_title("loop_cols=False")
#ax2.legend(loc='center left', bbox_to_anchor=(1, 0.5)) # No need for this
plt.subplots_adjust(left=0.08,right=0.88,wspace=0.55)
plt.show()
答案 1 :(得分:0)
以上示例中未修改图例,在两种情况下都将创建新的图例。此问题与legend()
上的标签取决于matplotlib.lines.Line2D
的行为方式有关。文档中的相关部分是
1。自动检测要在图例中显示的元素
要自动添加到图例的元素, 当您不传递任何额外参数时。
在这种情况下,标签取自艺术家。您可以指定 他们可以在艺术家创作时或通过致电 :meth:
~.Artist.set_label
对艺术家的方法:line, = ax.plot([1, 2, 3], label='Inline label') ax.legend()
或::
line.set_label('Label via method') line, = ax.plot([1, 2, 3]) ax.legend()
特定行可以从自动图例元素中排除 通过定义以下划线开头的标签进行选择。这是 所有艺术家的默认设置,因此不加任何呼叫
Axes.legend
参数且未手动设置标签将导致没有 图例正在绘制。2。标记现有图元素
为轴上已经存在的线制作图例(通过绘图) 例如),只需使用可迭代的字符串调用此函数, 每个图例项一个。例如:
ax.plot([1, 2, 3]) ax.legend(['A simple line'])
注意:不建议使用这种使用方式,因为 绘图元素和标签仅按其顺序隐含并且可以 容易混淆。
在第一种情况下,未设置标签
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'a': [1, 5, 3], 'b': [1, 3, -4]})
fig, axes = plt.subplots(1)
lines = axes.plot(df)
print(lines[0].get_label())
print(lines[1].get_label())
_line0
_line1
因此第一次调用带有标签的legend()
属于情况 2。。再次调用legend
时,它不带标签,属于大小写 1。。如您所见,Legend
实例不同,第二个实例正确地抱怨有{ {1}}
No handles with labels found to put in legend.
在第二种情况下,这些行已正确标记,因此第二次调用l1 = axes.legend(['a', 'b'])
print(repr(l1))
<matplotlib.legend.Legend object at 0x7f05638b7748>
l2 = axes.legend(loc='upper left')
No handles with labels found to put in legend.
print(repr(l2))
<matplotlib.legend.Legend object at 0x7f05638004e0>
会正确推断出标签。
legend()