[英]Matplotlib: Lines on Top of Bars, Legend on the Left, No Splines
I'm having trouble tweaking the graph below.我在调整下图时遇到问题。
Here's what the dataframe looks like:这是数据框的样子:
Year Some All Ratio
0 2016 9 157 0.057325
1 2017 13 189 0.068783
2 2018 21 216 0.097222
3 2019 18 190 0.094737
4 2020 28 284 0.098592
Here's what I want to do:这是我想要做的:
zorder
parameter and it didn't help.我尝试使用zorder
参数但没有帮助。 I also tried switch the order of the axes object, but I couldn't get the line to be assigned to the primary axis.我也试过切换轴对象的顺序,但我无法将线分配给主轴。figsize
argument.您会在下面的代码中注意到我使用了一个有点大的figsize
参数。 If I use a smaller one, the legend will magically move to the left, but I don't want to use a smaller one.如果我使用较小的,图例会神奇地向左移动,但我不想使用较小的。ax.annotate
, but I couldn't center the values automatically.我尝试遍历每个值并使用ax.annotate
单独注释条形图,但我无法自动将这些值居中。 In this minimal example, all the values are three digits long, but in the original data I have numbers that four digits long and I couldn't find a good way to make it centered for all of them.在这个最小的例子中,所有的值都是三位数长,但在原始数据中,我有四位数长的数字,我找不到一个好方法让它为所有这些数字居中。The code to help people get started follows below.下面是帮助人们入门的代码。
data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
'Ratio': {0: 0.05732484076433121,
1: 0.06878306878306878,
2: 0.09722222222222222,
3: 0.09473684210526316,
4: 0.09859154929577464}}
df = __import__("pandas").DataFrame(data)
ax = df.plot(x="Year", y="Ratio",
kind="line", linestyle='-', marker='o', color="orange",
figsize=((24,12))
)
df.plot(x="Year", y="All",
kind="bar", ax=ax, secondary_y=True
)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
Your asking quite a number of things.你问了很多事情。
ax1.legend(loc='upper left')
, but in our case with two plots this seems to always draw a second legend with the last drawn plot as only entry.通常你只需执行ax1.legend(loc='upper left')
,但在我们有两个图的情况下,这似乎总是绘制第二个图例,最后绘制的图作为唯一条目。set_bbox_to_anchor
with little documentation .有一个函数set_bbox_to_anchor
, 文档很少。 It defines some box (x, y, width, height) , but there is also a seemingly inaccessible loc
parameter that controls how the box and the position relate.它定义了一些盒子 (x, y, width, height) ,但还有一个看似不可访问的loc
参数控制盒子和位置的关系。 "The default for loc
is loc="best"
which gives unpredictable results when the bbox_to_anchor argument is used." “ loc
的默认值是loc="best"
,当使用 bbox_to_anchor 参数时会产生不可预测的结果。” Some experimentation might be needed.可能需要进行一些实验。 The best solution, is to guard the最好的解决办法,就是守护zorder
not to work as desired).要移除脊椎,似乎有两个轴相互重叠(这也可能导致zorder
无法按预期工作)。 You'll want to hide the spines of both of them.你会想要隐藏它们的脊椎。ax1.axes.yaxis.set_ticks([])
.要删除刻度,请使用ax1.axes.yaxis.set_ticks([])
。ax2.yaxis.tick_left()
.要将 ax2 刻度切换到左侧,请使用ax2.yaxis.tick_left()
。import pandas as pd
from matplotlib import pyplot as plt
data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
'Ratio': {0: 0.05732484076433121,
1: 0.06878306878306878,
2: 0.09722222222222222,
3: 0.09473684210526316,
4: 0.09859154929577464}}
df = pd.DataFrame(data)
ax1 = df.plot(x="Year", y="All",
kind="bar",
)
for i, a in df.All.items():
ax1.text(i, a, str(a), ha='center', va='bottom', fontsize=18)
xlims = ax1.get_xlim()
ax2 = df.plot(x="Year", y="Ratio",
kind="line", linestyle='-', marker='o', color="orange", ax=ax1, secondary_y=True,
figsize=((24, 12))
)
ax2.set_xlim(xlims) # needed because the line plot shortens the xlims
# ax1.get_legend().set_bbox_to_anchor((0.03, 0.9, 0.1, 0.1)) # unpredictable behavior when loc='best'
# ax1.legend(loc='upper left') # in our case, this would create a second legend
ax1.get_legend().remove() # remove badly placed legend
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(handles=handles1 + handles2, # create a new legend
labels=labels1 + labels2,
loc='upper left')
# ax1.yaxis.tick_right() # place the yticks for ax1 at the right
ax2.yaxis.tick_left() # place the yticks for ax2 at the left
ax2.set_ylabel('Ratio')
ax2.yaxis.set_label_position('left')
ax1.axes.yaxis.set_ticks([]) # remove ticks
for ax in (ax1, ax2):
for where in ('top', 'right'):
ax.spines[where].set_visible(False)
plt.show()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.