So I am trying to use this data: [1,2,3], [3,4,5]
to plot a vertical bar chart, horizontal bar chart and a blank plot in one pyplot figure that would look like the image in this example:
but my code so far plots slightly differently as seen here. Look at the x-axis on bar chart 1 and y-axis on horizontal bar chart 2. I'm trying to get bar chart 1 x-axis to look like the y-axis on barh. Now the numbers are not in decimals (eg 1.0,2.0) and there are no numbers shown for 1.5,2.5 and 3.5. (I made some progress thanks to unutbu's explanation):
Please see my updated code below, I am totally new to plotting and still trying to understand how this works:
import matplotlib.pyplot as plt
import numpy as np
plt.close()
fig, ax = plt.subplots(ncols=3)
sid = [1, 2, 3]
bel = [3, 4, 5]
y_pos = np.arange(len(sid))+1.5
ax[0].bar(y_pos, bel, align='center', alpha=0.5)
ax[0].set_xticks(y_pos, sid)
ax[0].set_xlim(1.0,4.0)
ax[0].set_ylim(0, 5)
y_pos = np.arange(len(sid)) + 1
ax[1].barh(y_pos, bel, height=0.9, align='edge', alpha=0.5)
ax[1].set_yticks(np.linspace(1, 4, 7))
ax[1].set_xticks(np.arange(0,6,1))
ax[1].set_ylim(1, 4)
sid = []
bel = []
y_pos = np.arange(len(sid))
ax[2].barh(y_pos, bel, align='center', alpha=0.5)
ax[2].set_yticks([0.0,0.2,0.4,0.6,0.8,1.0])
ax[2].set_xticks([0.0,0.2,0.4,0.6,0.8,1.0])
ax[2].set_ylim(0, 1)
plt.tight_layout()
plt.show()
Let's focus on the middle axes. You could use
y_pos = np.arange(len(sid))+1
plt.barh(y_pos, bel, height=0.9, align='edge', alpha=0.5)
plt.yticks(np.linspace(1, 4, 7))
plt.ylim(1, 4)
to produce the desired result. Notice that adding 1 to y_pos
makes y_pos
equal to array([1, 2, 3])
since adding a constant to a NumPy array adds that constant to each element in the array:
In [11]: np.arange(len(sid))
Out[11]: array([0, 1, 2])
In [12]: np.arange(len(sid))+1
Out[12]: array([1, 2, 3])
Thus, plt.barh(y_pos, ..., align='edge')
places the bottom edge of the bars at y-locations 1, 2, 3.
np.linspace(1, 4, 7)
generates 7 equally spaced values between 1 and 4:
In [13]: np.linspace(1, 4, 7)
Out[13]: array([1. , 1.5, 2. , 2.5, 3. , 3.5, 4. ])
plt.yticks(np.linspace(1, 4, 7))
tells matplotlib to label those locations.
plt.ylim(1, 4)
sets the y-limits of the y-axis to range from 1 to 4.
On a stylistic note, you might want to consider switching to the "object-oriented" style of matplotlib programming . Instead of callling plt.subplot(1, 3, 2)
to activate the second of 3 axes, you could use
fig, ax = plt.subplots(ncols=3)
to generate the 3 axes. This gives you an object ax
which is a sequence of 3 axes.
The attraction of coding this way is that you now have a "physical" object to which you can send commands.
Before, when you focus on a single line like
plt.barh(y_pos, bel, height=0.9, align='edge', alpha=0.5)
it was not immediately clear on which axes the bar chart will appear. Now, using the object-oriented matplotlib coding style, this command would be
ax[1].barh(y_pos, bel, height=0.9, align='edge', alpha=0.5)
so you would know immediately that the second axes is being drawn upon.
Although it may be a little more verbose (ie more typing), as your programs grow in complexity, I think you'll find the "object-oriented" style produces clearer, more readable code.
Here is what your code would look like:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(ncols=3)
sid = [1, 2, 3]
bel = [3, 4, 5]
y_pos = np.arange(len(sid)) + 1
ax[0].bar(y_pos, bel, width=0.9, align='edge', alpha=0.5)
ax[0].set_xticks(np.linspace(1, 4, 7))
ax[0].set_ylim(0, 5)
ax[1].barh(y_pos, bel, height=0.9, align='edge', alpha=0.5)
ax[1].set_yticks(np.linspace(1, 4, 7))
ax[1].set_xticks(np.arange(0,6,1))
ax[1].set_ylim(1, 4)
sid = []
bel = []
y_pos = np.arange(len(sid))
ax[2].barh(y_pos, bel, align='center', alpha=0.5)
ax[2].set_yticks([0.0,0.2,0.4,0.6,0.8,1.0])
ax[2].set_xticks([0.0,0.2,0.4,0.6,0.8,1.0])
ax[2].set_ylim(0, 1)
plt.tight_layout()
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.