Matplotlib bar graphs: increase spacing between bars - python

I'm new to matplotlib and it seems like there's no direct method for increasing the space between bars in a bar graph rendering of data. There are posts on this but the responses say that one has to play with the width of bars or the scale of the x axis which is not what I'm looking for because that will just make my bar skinnier or lead to overlapping and scaling the x axis wouldn't work for non-numerical tick values (right?). I would specifically like to increase the space between the bars which makes sense for the data below:
import matplotlib.pyplot as plt
plt.bar('state','n_incidents',data=top_5_gun_violence_states)
plt.xlabel('States')
plt.ylabel('# of incidents')
plt.title('Statewise gun violence graph')
plt.xticks(rotation=90)
# plt.figure(figsize=(20, 3))
plt.show()
The output looks like this:
matplotlib bar plot
Clearly, this needs more spacing between bars as state names are squeezed together. Any help would be appreciated! Thanks!

Related

Black bar covering my x labels for matplotlib plot?

I am trying to play a figure and I am having a black box pop up on the bottom of the plot where the x labels should be. I tried this command from a similar question on here in the past:
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
But the problem was still the same. Here is my current code:
import pylab
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
df['date'] = df['date'].astype('str')
pos = np.arange(len(df['date']))
plt.bar(pos,df['value'])
ticks = plt.xticks(pos, df['value'])
And my plot is attached here. Any help would be great!
pos = np.arange(len(df['date'])) and ticks = plt.xticks(pos, df['value']) are causing the problem you are having. You are putting an xtick at every value you have in the data frame.
Don't know how you data looks like and what's the most sensible way to do this. ticks = plt.xticks(pos[::20], df['value'].values[::20], rotation=90) will put a tick every 20 rows that would make the plot more readable.
It actually is not a black bar, but rather all of your x-axis labels being crammed into too small of a space. You can try rotating the axis labels to create more space or just remove them all together.

Bar chart in matplotlib shows less bars when having big range on x coordinates

What am I doing wrong here with a bar chart in python and matplotlib? The first plot is good, the second has a much wider range on the x-axis up to 1500. Notice in the second plot that most of the bars on the low scale disappear, but also the bar at 1500 is not shown.
I tried setting the width=0.8 in the bar() method, but that does not help.
With a logarithmic x-axis (using plt.xscale('log') ) it seems to work fine
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(12, 6))
plt.bar(np.array([1,2,3,4,11,12]), np.array([10,2,1,1,3,10]))
plt.show()
#Then I close the figure and run this:
plt.bar(np.array([1,2,3,4,11,1500]), np.array([10,2,1,1,3,10]))
plt.show()
Bars are by default 1 data units wide. The axes is ~600 pixels wide, but has ~1500 units. The chances you will see any single bar is hence 600/1500*1 = 40%. In that sense it's bad luck that you don't see the bar at x=1500. The other bars are so close together that you don't see which one of them is actually shown.
Instead of relying on the chances of seeing a bar, you would rather make the bar wide enough such that it can be seen safely. E.g. using a width of 5
plt.bar(np.array([1,2,3,4,11,1500]), np.array([10,2,1,1,3,10]), width=5)
Alternatively you could also show a stem plot, i.e. a plot with lines instead of bars,
plt.stem(np.array([1,2,3,4,11,1500]), np.array([10,2,1,1,3,10]),markerfmt=" ", basefmt=" ")
plt.ylim(0,None)

How do I change the size of the plot and prevent overlapping in the y axis?

I have plotted a horizontal bar graph with a large number of horizontal bars.
Is there any way I could prevent the overlapping of the y axis titles and the bars in the bar graphs. Or the only way is increasing the height of the graph?
I have tried using:
plt.figure(figsize=(13,14)) but it doesn't work also when I try replacing plt.show() by plt.figure(figsize=(13,14)).show()
I get the error :
UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure
"matplotlib is currently using a non-GUI backend, "
import matplotlib.pyplot as plt
plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
length=[477, 531, 568, 651, 1599, 1605, 1635, 1960, 2009, 2446, 2668, 3308, 3433, 3889, 4180, 4529, 5388, 6378, 7588, 7671, 7679, 8505, 8763, 8863, 8910, 9028, 9030, 10124, 10722, 10894, 11103, 11388, 12167, 12464, 14217, 14367, 14472, 16501, 18765, 19407, 19627, 20795, 21727, 21912, 22620, 24871, 25045, 25625, 25867, 27512, 30380, 30424, 31264, 32070, 32277, 33879, 35749, 35932, 37406, 37414, 40040, 42070, 42516, 42804, 44381, 46314, 48216, 48349, 50547, 50796, 53759, 54716, 65888, 81106, 86280, 104522, 179133, 189921]
y_pos = np.arange(len(length))
error = np.random.rand(len(length))
plt.barh(y_pos, length, xerr=error*2, align='center', alpha=0.3)
plt.yticks(y_pos, length)
plt.xlabel('Lengths')
plt.title('Comparison of different cuts')
plt.show()
This is the graph I am referring to:
You are plotting a very large amount of bars in a small space and labeling each tick mark. The easiest way to make this legible is with increasing the length of the plot. Using plt.figure(figsize=(10,20)) instantly makes the plot legible for me.
If you want to keep the figure the same size, you have a few other knobs to tweak. First you can control the height of each horizontal bar with the height parameter. It defaults to .8 so try using a lower value. You can also control the size of the yticks with the fontsize parameter. Tweaking these parameters will give you non-overlapping bars/ticks but at a cost of resolution. To increase the resolution upon saving your figure with plt.savefig, use the dpi parameter to set it higher than the default.
The number of labels on the y-axis is quite high, so it will be hard to get them all to fit within a plot. Increasing the size of the plot will help, and another thing that might help, is to decrease the font size of the y-tick labels like this:
ax = plt.gca()
for tick in ax.yaxis.get_major_ticks():
tick.label.set_fontsize(6)
Maybe you could also just give every other, or third y-tick label.

Matplotlib: How do I have the xtick labels apear on the other side of the x-axis?

In this bar chart:
How do I make the x-axis labels appear in the bars of the bar-chart and left-aligned with the x-axis?
I tried the ax.xaxis.labelpad() method but it does not seem to do anything.
you can set the y location of the ticks when you call set_xticklabels. So, if you set y to something small but positive, it should be placed inside the bars.
For example:
import matplotlib.pyplot as plt
fig,ax = plt.subplots(1)
ax.bar([0,1,2,3],[7900,9400,8700,9990],facecolor='#5080B0',edgecolor='k',width=0.3)
ax.set_xticks([0.15,1.15,2.15,3.15])
ax.set_xticklabels(['beek1','beek2','orbath','Kroo'],
rotation='vertical',y=0.05,va='bottom')
Produces the following plot:

autofmt_xdate deletes x-axis labels of all subplots

I use autofmt_xdate to plot long x-axis labels in a readable way. The problem is, when I want to combine different subplots, the x-axis labeling of the other subplots disappears, which I do not appreciate for the leftmost subplot in the figure below (two rows high). Is there a way to prevent autofmt_xdate from quenching the other x-axis labels? Or is there another way to rotate the labels? As you can see I experimented with xticks and "rotate" as well, but the results were not satisfying because the labels were rotated around their center, which resulted in messy labeling.
Script that produces plot below:
from matplotlib import pyplot as plt
from numpy import arange
import numpy
from matplotlib import rc
rc("figure",figsize=(15,10))
#rc('figure.subplot',bottom=0.1,hspace=0.1)
rc("legend",fontsize=16)
fig = plt.figure()
Test_Data = numpy.random.normal(size=20)
fig = plt.figure()
Dimension = (2,3)
plt.subplot2grid(Dimension, (0,0),rowspan=2)
plt.plot(Test_Data)
plt.subplot2grid(Dimension, (0,1),colspan=2)
for i,j in zip(Test_Data,arange(len(Test_Data))):
plt.bar(i,j)
plt.legend(arange(len(Test_Data)))
plt.subplot2grid(Dimension, (1,1),colspan=2)
xticks = [r"%s (%i)" % (a,b) for a,b in zip(Test_Data,Test_Data)]
plt.xticks(arange(len(Test_Data)),xticks)
fig.autofmt_xdate()
plt.ylabel(r'$Some Latex Formula/Divided by some Latex Formula$',fontsize=14)
plt.plot(Test_Data)
#plt.setp(plt.xticks()[1],rotation=30)
plt.tight_layout()
#plt.show()
This is actually a feature of the autofmt_xdate method. From the documentation of the autofmt_xdate method:
Date ticklabels often overlap, so it is useful to rotate them and right align them. Also, a common use case is a number of subplots with shared xaxes where the x-axis is date data. The ticklabels are often long, and it helps to rotate them on the bottom subplot and turn them off on other subplots, as well as turn off xlabels.
If you want to rotate the xticklabels of the bottom right subplot only, use
plt.setp(plt.xticks()[1], rotation=30, ha='right') # ha is the same as horizontalalignment
This rotates the ticklabels 30 degrees and right aligns them (same result as when using autofmt_xdate) for the bottom right subplot, leaving the two other subplots unchanged.

Categories