简体   繁体   中英

How to fill or shade area between two corresponding points in stacked bar plots in Python using matplotlib?

I have a dataframe df which looks as follows:

A   B
X   5   7
Y   10  5

df.to_dict() gives the following:

{'A': {'X': 5, 'Y': 10}, 'B': {'X': 7, 'Y': 5}}

I have created a stacked bar plot using

df.plot(kind = "bar", stacked = True)

It look as follows: 在此处输入图像描述

I want to shade the region between A in X and Y bar, and the same for B. The shaded region reflect how the value of A and B has changed between X and Y. It should look something as shown: 在此处输入图像描述

How can I fill areas in between these two stacked bar plots using matplotlib in Python keeping the original structure of bar plot intact?

Here's another fill_between with more general approach:

# loop through the bars to get the bottom and top points
bottoms = []
tops = []
for patch in ax.patches:
    x,y = patch.get_xy()
    w,h = patch.get_width(), patch.get_height()
    
    bottoms += [(x,y), (x+w, y)]
    tops += [(x, y+h), (x+w, y+h)]

# convert to numpy for easy slicing
tops = np.array(tops)
bottoms = np.array(bottoms)

# extract the x coordinates
x = np.unique(bottoms[:,0])
num_x = len(x)

# fill between each bottom and top pairs
for i in range(0, len(bottoms), num_x):
    plt.fill_between(x, tops[i:i+num_x, 1], bottoms[i:i+num_x, 1], alpha=0.5)

Output:

在此处输入图像描述

Here is a way using fill_between .

ax = df.plot(kind = "bar", stacked = True)
plt.fill_between(x = [ax.patches[0].get_x() + ax.patches[0].get_width(), 
                      ax.patches[1].get_x()], 
                 y1 = 0, 
                 y2 = [ax.patches[0].get_y() + ax.patches[0].get_height(),
                       ax.patches[1].get_y() + ax.patches[1].get_height()], 
                color = ax.patches[0].get_facecolor(), alpha=0.5)
plt.fill_between(x = [ax.patches[2].get_x() + ax.patches[2].get_width(), 
                      ax.patches[3].get_x()], 
                 y1 = [ax.patches[0].get_y() + ax.patches[0].get_height(),
                       ax.patches[1].get_y() + ax.patches[1].get_height()], 
                 y2 = [ax.patches[2].get_y() + ax.patches[2].get_height(),
                       ax.patches[3].get_y() + ax.patches[3].get_height()], 
                color = ax.patches[2].get_facecolor(), alpha=0.5)
plt.plot()

Ok. I found an easy way myself using ax.fill_between() . For x, I specify [0.25, 0.75]. 0.25 refers to the right edge of bar for X and 0.75 refers to the left edge of bar for Y. The positions in X-axis with ticks for X and Y are 0 and 1 respectively.

For y1 and y2, I specify the y-coordinates of lower and upper edges to be filled in between respectively.

 fig, ax = plt.subplots() ax = df.plot(kind = "bar", stacked = True, ax = ax, color = ["blue","orange"]) ax.fill_between(x =[0.25,0.75], y1 = [0, 0], y2 = [5, 10], color = "blue", alpha = 0.5) ax.fill_between(x =[0.25, 0.75], y1 = [5, 10], y2 = [12, 15], color = "orange", alpha = 0.5) plt.show()

I get something as shown: 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM