将垂直线添加到多个水平条形图中

时间:2019-04-17 11:08:06

标签: python pandas seaborn

我正在将多条形图生成为水平条形图,现在我需要做的是在特定位置(基于x轴值)在每个水平条形图中添加注释(基本上创建一条垂直线)。对于每个y轴,其中y轴是分类(名称),x轴是数字(整数)。

我查看了axis.vlines,但无法正常工作。

import seaborn as sns
import matplotlib.pyplot as plt
crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
crashes['max_range'] = crashes['total'] * 0.85
sns.set_color_codes("muted")
sns.set(style="whitegrid")
sns.barplot(x="total", y="abbrev", data=crashes, label="", color="r")
sns.barplot(x="max_range", y="abbrev", data=crashes, label="", color="y")
sns.barplot(x="alcohol", y="abbrev", data=crashes,label="normal range", color="g")

#dummy data for the "vertical lines" i want to plot
crashes['actual'] = crashes['alcohol'] * 1.85

上面的代码创建了一个像这样的图:

https://seaborn.pydata.org/examples/horizontal_barplot.html

现在,我基本上想在基础数据帧的另一列中的绘图的每一行(因此绘图中的每个条形图)添加一条垂直线。

1 个答案:

答案 0 :(得分:1)

axis.vlines就足够了。首先,为条形图标签提取y点。然后,我将这些点的x值制作成字典。比我用axis.vlines在条上画一条红线。

import seaborn as sns
import matplotlib.pyplot as plt

crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
crashes['max_range'] = crashes['total'] * 0.85
sns.set_color_codes("muted")
sns.set(style="whitegrid")
# Store the returned axes in a variable
ax = sns.barplot(x="total", y="abbrev", data=crashes, label="", color="r")
ax = sns.barplot(x="max_range", y="abbrev", data=crashes, label="", color="y")
ax = sns.barplot(x="alcohol", y="abbrev", data=crashes,label="normal range", color="g")

#dummy data for the "vertical lines" i want to plot
crashes['actual'] = crashes['alcohol'] * 1.85


#### MY ADDITIONS ####

# Form dictionary of bar chart keys (i.e. Y axis data, here it is "abbrev") to
# corresponding y and x points
y_labs = list(ax.get_yticklabels())
y_tic_pos = list(ax.get_yticks())
y_tick_vals = {}
for i in range(len(y_tic_pos)):
    y_tick_vals[y_labs[i].get_text()] = y_tic_pos[i]
x_points = {lab:crashes[crashes["abbrev"] == lab]["actual"].values[0] for lab in y_tick_vals}

# for each of the relevant y axis, draw a vertical line
for key in y_tick_vals:
    c_y = y_tick_vals[key]
    c_x = x_points[key]
    # I just did some trial and error to find out that each bar is 0.5 wide;
    # this may not be the case for other plots.
    c_ymin = c_y - 0.25
    c_ymax = c_y + 0.25

    ax.vlines(c_x, c_ymin, c_ymax, colors="r")

plt.show()

应该有一种更优雅的方式来做到这一点;这是我想出的第一个原型。


PS 。您说您尝试使用axis.vlines,但不包含用于向我们展示您的尝试的代码。我认为这是您的问题被否决的原因之一。