Home > front end >  How can I remove space between bars while plotting bar plot using pandas and matplotlib in Python?
How can I remove space between bars while plotting bar plot using pandas and matplotlib in Python?

Time:05-16

I have a pandas dataframe df which looks as follows:

Base    Current level   New fan New refrigerator    Unplug unused appliances    Run washing machine with full load  Fix leakages    After three months  Install smart thermostat    Replace light bulbs with LED lights Replace desktop with laptop After six months
0   0   150.0   0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1   150 0.0 10.0    0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2   160 0.0 0.0 15.0    0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
3   160 0.0 0.0 0.0 15.0    0.0 0.0 0.0 0.0 0.0 0.0 0.0
4   145 0.0 0.0 0.0 0.0 15.0    0.0 0.0 0.0 0.0 0.0 0.0
5   140 0.0 0.0 0.0 0.0 0.0 5.0 0.0 0.0 0.0 0.0 0.0
6   0   0.0 0.0 0.0 0.0 0.0 0.0 140.0   0.0 0.0 0.0 0.0
7   115 0.0 0.0 0.0 0.0 0.0 0.0 0.0 25.0    0.0 0.0 0.0
8   105 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10.0    0.0 0.0
9   95  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10.0    0.0
10  0   0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 95.0

df.to_dict() is given for reference:

{'Base': {0: 0,
  1: 150,
  2: 160,
  3: 160,
  4: 145,
  5: 140,
  6: 0,
  7: 115,
  8: 105,
  9: 95,
  10: 0},
 'Current level': {0: 150.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'New fan': {0: 0.0,
  1: 10.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'New refrigerator': {0: 0.0,
  1: 0.0,
  2: 15.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'Unplug unused appliances': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 15.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'Run washing machine with full load': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 15.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'Fix leakages': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 5.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'After three months': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 140.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'Install smart thermostat': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 25.0,
  8: 0.0,
  9: 0.0,
  10: 0.0},
 'Replace light bulbs with LED lights': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 10.0,
  9: 0.0,
  10: 0.0},
 'Replace desktop with laptop': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 10.0,
  10: 0.0},
 'After six months': {0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  5: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  9: 0.0,
  10: 95.0}}

I want to plot a waterfall chart using this data. For this, I plotted a stacked bar plot using the code below and using column Base as bottom.

colors = ["royalblue","green","green","red","red","red","royalblue",
        "red","red","red","royalblue"]

fig = df.loc[:,"Current level":].plot(kind = "bar",
                               bottom = df["Base"],
                     
                               color = colors)


selected_patches = fig.patches[0], fig.patches[20], fig.patches[40]


plt.legend(selected_patches, ["Base", "Rise", "Fall"], loc = "upper right")

plt.xticks(ticks = np.arange(0, len(df)), labels = df.columns[1:], rotation = 90)

plt.title("My electricity saving plan")

plt.ylabel("kWh consumption")

This returned me the following plot: enter image description here

The default width of the bar plot i.e. 0.8 enter image description here

However, now the position of ticks and labels is distorted. How can I set the width of the bars such that the bars look wide, the space between bars is none or small, and the ticks and labels in the x-axis are still in the same position as bars?

CodePudding user response:

The problem is that each point in the x axis is allocating space for 10 different bars. So any size you put, you will always have 9 empty spaces. Instead, you should restructure the df before plotting:

import matplotlib.pyplot as plt

colors = ["royalblue","green","green","red","red","red","royalblue",
        "red","red","red","royalblue"]

fig = df.loc[:,"Current level":].T.max(axis=1).plot(kind='bar', bottom=df['Base'], width=1, color=colors)

selected_patches = fig.patches[0], fig.patches[2], fig.patches[4]
plt.legend(selected_patches, ["Base", "Rise", "Fall"], loc = "upper right")

plt.xticks(ticks = np.arange(0, len(df)), labels = df.columns[1:], rotation = 90)

plt.title("My electricity saving plan")

plt.ylabel("kWh consumption")
plt.show()

Result:

enter image description here

Notice that the patches indices also changed, since we don't have all the empty ones anymore.

  • Related