I am trying to generate a stacked bar plot to keep track of three parameters for every hour over multiple days. The picture of a sample plot is SamplePlot . However, I have had no success with plotting this in python. The fact that I am a beginner in python, makes matters worse.
Two attempts made previously to answer this questions are: Horizontal stacked bar chart in Matplotlib and stack bar plot in matplotlib and add label to each section (and suggestions) . However, I have not been able to achieve the desired results following any of the above solutions.
Can anyone please provide me with guidance as to how to generate the plot or point me in the direction?
Edit 1: The code that I have written is as follows:
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
status_day1 = [[0.2,0.3,0.5], [0.1,0.3,0.6], [0.4,0.4,0.2], [0.6,0.1,0.4]]
status_day2 = [[0.1,0.2,0.7], [0.3,0.2,0.5], [0.1,0.5,0.4], [0.2,0.5,0.3]]
day = ('Day1', 'Day2')
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111)
for x in range(0,4): #Looping through every hour
for y in range(0,3): #Looping through every parameter
if y==0:
ax.bar(1, status_day1[x][y],color='b',align='center')
elif y==1:
ax.bar(1, status_day1[x][y],color='r',align='center')
else:
ax.bar(1, status_day1[x][y],color='g',align='center')
# I am assuming that the three parameters for every hour are getting stacked on top of one another
for x in range(0,4):
for y in range(0,3):
if y==0:
ax.bar(1, status_day2[x][y],color='b',align='center')
elif y==1:
ax.bar(1, status_day2[x][y],color='r',align='center')
else:
ax.bar(1, status_day2[x][y],color='g',align='center')
ax.set_xticklabels(day)
ax.set_xlabel('Day')
ax.set_ylabel('Hours')
plt.show()
You need to keep track of the bottom of your bars, see the stacked bar plot example in the matplotlib docs: http://matplotlib.org/examples/pylab_examples/bar_stacked.html
Also, you can get rid of most of the more uglier loop code by using python's zip
and enumerate
functions as well as
for value in data:
print(value)
instead of
for i in range(len(data)):
print(data[i])
With this I get the expected result:
import matplotlib.pyplot as plt
status_day1 = [
[0.2, 0.3, 0.5],
[0.1, 0.3, 0.6],
[0.4, 0.4, 0.2],
[0.6, 0.1, 0.4],
]
status_day2 = [
[0.1, 0.2, 0.7],
[0.3, 0.2, 0.5],
[0.1, 0.5, 0.4],
[0.2, 0.5, 0.3],
]
days = ('Day1', 'Day2')
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(1, 1, 1)
for day, data in enumerate((status_day1, status_day2)):
bottom = 0
for hour in data: # Looping through every hour
for value, color in zip(hour, ('b', 'r', 'g')):
ax.bar(
day,
value,
bottom=bottom,
color=color,
align='center',
)
bottom += value
ax.set_xticks([0, 1])
ax.set_xticklabels(days)
ax.set_xlabel('Day')
ax.set_ylabel('Hours')
plt.show()
@MaxNoe has already answered the question quite elegantly by using zip and enumerate. However, for people who are not familiar with zip and enumerate, the following code achieves the desired results:
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
status_day1 = [[0.2,0.3,0.5], [0.1,0.3,0.6], [0.4,0.4,0.2], [0.6,0.1,0.3]]
status_day2 = [[0.1,0.2,0.7], [0.3,0.2,0.5], [0.1,0.5,0.4], [0.2,0.5,0.3]]
xval = [0.,1.,2.] #The places where the ticks are going to be on the x-axis
bottom_append = 0 #Counter to keep track of the bar (this is quite important)
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111)
for x in range(0,4): #Looping through every hour
for y in range(0,3): #Looping through every parameter
if y==0:
if x==0:
print(status_day1[x][y], bottom_append)
ax.bar(0, status_day1[x][y], width = 0.3, color='blue',align='center')
bottom_append = bottom_append+status_day1[x][y]
else:
print(status_day1[x][y], bottom_append)
ax.bar(0, status_day1[x][y], width = 0.3, color='blue',align='center',bottom=bottom_append)
bottom_append = bottom_append+status_day1[x][y]
elif y==1:
print(status_day1[x][y], bottom_append)
ax.bar(0, status_day1[x][y], width = 0.3, color='red',align='center', bottom=bottom_append)
bottom_append = bottom_append+status_day1[x][y]
else:
print(status_day1[x][y], bottom_append)
ax.bar(0, status_day1[x][y], width = 0.3, color='green',align='center', bottom=bottom_append)
bottom_append = bottom_append+status_day1[x][y]
bottom_append = 0
# Code is exactly same as the above, only takes into account day2
for x in range(0,4): #Looping through every hour
for y in range(0,3): #Looping through every parameter
if y==0:
if x==0:
print(status_day2[x][y], bottom_append)
ax.bar(1, status_day2[x][y], width = 0.3, color='blue',align='center')
bottom_append = bottom_append+status_day2[x][y]
else:
print(status_day2[x][y], bottom_append)
ax.bar(1, status_day2[x][y], width = 0.3, color='blue',align='center',bottom=bottom_append)
bottom_append = bottom_append+status_day2[x][y]
elif y==1:
print(status_day2[x][y], bottom_append)
ax.bar(1, status_day2[x][y], width = 0.3, color='red',align='center', bottom=bottom_append)
bottom_append = bottom_append+status_day2[x][y]
else:
print(status_day2[x][y], bottom_append)
ax.bar(1, status_day2[x][y], width = 0.3, color='green',align='center', bottom=bottom_append)
bottom_append = bottom_append+status_day2[x][y]
# Setting the properties of the subplot in an attempt to beautify it
Label1 = mpatches.Patch(color='blue', label='Label1')
Label2 = mpatches.Patch(color='green', label='Label2')
Label3 = mpatches.Patch(color='red', label='Label3')
ax.legend(handles=[Label1, Label2, Label3], loc=1)
ax.set_xticks(xval)
ax.set_xticklabels(["Day1","Day2","Day3"])
ax.set_xlabel('Day')
ax.set_ylabel('Hours')
plt.show()
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.