I have three lists: x, y and w as shown: x is the name of objects. y is its height and w is its width.
x = ["A","B","C","D","E","F","G","H"]
y = [-25, -10, 5, 10, 30, 40, 50, 60]
w = [30, 20, 25, 40, 20, 40, 40, 30]
I'd like to plot these values in a bar plot in Python such that y represents height and w represents width of the bar.
When I plot it using
colors = ["yellow","limegreen","green","blue","red","brown","grey","black"]
plt.bar(x, height = y, width = w, color = colors, alpha = 0.8)
Next, I tried to normalize the widths so that the bars would not overlap with each other using
w_new = [i/max(w) for i in w]
plt.bar(x, height = y, width = w_new, color = colors, alpha = 0.8)
#plt.axvline(x = ?)
plt.xlim((-0.5, 7.5))
I get much better results than before as shown:
However, the gaps between the bars are still uneven. For example, between B and C, there is large gap. But between F and G, there is no gap.
I'd like to have plots where there is even gap width or no gap between two consecutive bars. It should look something as shown:
How can I create this type of plot in Python? Is it possible using any data visualization libraries such as matplotlib, seaborn or Plotly? Is there any alternative to do it if the data is available in dataframe?
Additionally, I'd like to add labels for A, B, C, etc. to the right of the plot and rather have actual width of the bar as labels on the x-axis (for e.g. depicted by red numbers in the x-axis plot above). I'd also like to add a vertical red line at distance 50 from the x-axis. I know this can be added using plt.axvline(x = ...)
But I am not sure what is the value I should state as x as the scale of W is not exact with the length of x-axis.
CodePudding user response:
IIUC, you can try something like this:
import matplotlib.pyplot as plt
x = ["A","B","C","D","E","F","G","H"]
y = [-25, -10, 5, 10, 30, 40, 50, 60]
w = [30, 20, 25, 40, 20, 40, 40, 30]
colors = ["yellow","limegreen","green","blue","red","brown","grey","black"]
#plt.bar(x, height = y, width = w, color = colors, alpha = 0.8)
xticks=[]
for n, c in enumerate(w):
xticks.append(sum(w[:n]) w[n]/2)
w_new = [i/max(w) for i in w]
a = plt.bar(xticks, height = y, width = w, color = colors, alpha = 0.8)
_ = plt.xticks(xticks, x)
plt.legend(a.patches, x)
Output:
Or change xticklabels for bar widths:
xticks=[]
for n, c in enumerate(w):
xticks.append(sum(w[:n]) w[n]/2)
w_new = [i/max(w) for i in w]
a = plt.bar(xticks, height = y, width = w, color = colors, alpha = 0.8)
_ = plt.xticks(xticks, w)
plt.legend(a.patches, x)
Output:
CodePudding user response:
I figured out an alternative way to do this.
x = ["A","B","C","D","E","F","G","H"]
y = [-25, -10, 5, 10, 30, 40, 50, 60]
w = [30, 20, 25, 40, 20, 40, 40, 30]
xpos = []
a = 0
for i in range(len(w)):
if i == 0:
a =w[i]
xpos.append(w[i]/2)
else:
a = w[i]
xpos.append(a - w[i]/2)
colors = ["yellow","limegreen","green","blue","red","brown","grey","black"]
fig = plt.bar(xpos,
height = y,
width = w,
color = colors,
alpha = 0.5,
)
plt.xticks(ticks = xpos, labels = w)
plt.xlim((0, 245))
plt.axvline(x = 150)
plt.legend(fig.patches, x)
plt.show()