Skip to content Skip to sidebar Skip to footer

Stacked Bar Plot From Loop Not Adding Different Components Of Bars

I have a dataset like this (column and row number can vary, which is why I need to define a function for plotting). import pandas as pd import numpy as np plot_df = pd.DataFrame({

Solution 1:

Problem number 1, if I understand you correctly is that the heigth of the bars is not 1 (i.e. the sum of all the fractions). Your code

p1 = plt.bar(ind, plot_df.iloc[:,0], width)
p2 = plt.bar(ind, plot_df.iloc[:,1], width)
...

creates four bar plots, allstartingfrom0 (on the y-axis). What we want is for p2 to start on top of p1, p3 to start on top of p2 and so on. To do this we can specify the bottom argument (which defaults to 0) in plt.bar. So,

p1 = plt.bar(ind, plot_df.iloc[:,0], width)
p2 = plt.bar(ind, plot_df.iloc[:,1], width, bottom=plot_df.iloc[:,0])
...

for p3 we want bottom to start on the sum of plot_df.iloc[:,0] and plot_df.iloc[:,1]. We can do this either explicitly or using np.sum like so np.sum(plot_df.iloc[:,:i]. The latter of course has the advantage that we can sum over an arbitrary number of columns (like you want in your function).

As for your function... I gave it a shot. You probably have to perfect it yourself

def bar_plot(plot_df):
    width = 0.35 # width of bars

    p_s = []
    p_s.append(plt.bar(ind, plot_df.iloc[:,0], width))
    for i in range(1,len(plot_df.columns)):
        p_s.append(plt.bar(ind, plot_df.iloc[:,i], width,
                           bottom=np.sum(plot_df.iloc[:,:i], axis=1)))

    plt.ylabel('[%]')
    plt.title('Responses by country')

    x_ticks_names = tuple([item for item in plot_df.index])

    plt.xticks(ind, x_ticks_names)
    plt.yticks(np.arange(0, 1.1, 0.1)) # ticks from, to, steps
    plt.legend(p_s, plot_df.columns)
    plt.show()

Solution 2:

The function provided by @mortysporty (all credit accordingly) can be tweaked to complete the desired task by just adding a few lines in the beginning that are referenced later:

import matplotlib.pyplot as plt
import numpy as np

def newest_bar_plot(plot_df):
    N = len(plot_df) # number of groups
    ind = np.arange(N) # x locations for the groups
    width = 0.35 # width of bars

    p_s = []
    p_s.append(plt.bar(ind, plot_df.iloc[:,0], width))
    for i in range(1,len(plot_df.columns)):
        p_s.append(plt.bar(ind, plot_df.iloc[:,i], width,
                           bottom=np.sum(plot_df.iloc[:,:i], axis=1)))

    plt.ylabel('[%]')
    plt.title('Responses by country')

    x_ticks_names = tuple([item for item in plot_df.index])

    plt.xticks(ind, x_ticks_names)
    plt.yticks(np.arange(0, 1.1, 0.1)) # ticks from, to, steps
    plt.legend(p_s, plot_df.columns)
    plt.show()

Post a Comment for "Stacked Bar Plot From Loop Not Adding Different Components Of Bars"