在matplotlib中修改轴属性

时间:2018-04-17 15:08:41

标签: python matplotlib

我想知道为什么取决于您在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()

图表图例正确设置为右侧

enter image description here

matplotlib

图表图例未设置为适当的位置

enter image description here

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

2 个答案:

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

enter image description here

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