Below is my code for a line graph. I would like another x label under the current one (so I can show the days of the week).
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns;sns.set()
sns.set()
data = pd.read_csv("123.csv")
data['DAY']=["01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"]
plt.figure(figsize=(15,8))
plt.plot('DAY','SWST',data=data,linewidth=2,color="k")
plt.plot('DAY','WMID',data=data,linewidth=2,color="m")
plt.xlabel('DAY', fontsize=20)
plt.ylabel('VOLUME', fontsize=20)
plt.legend()
EDIT: After following the documentation, I have 2 issues. The scale has changed from 31 to 16, and the days of the week do not line up with the day number.
data['DAY']=["01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"]
tick_labels=['1','\n\nThu','2','\n\nFri','3','\n\nSat','4','\n\nSun','5','\n\nMon','6','\n\nTue','7','\n\nWed','8','\n\nThu','9','\n\nFri','10','\n\nSat','11','\n\nSun','12','\n\nMon','13','\n\nTue','14','\n\nWed','15','\n\nThu','16','\n\nFri','17','\n\nSat','18','\n\nSun','19','\n\nMon','20','\n\nTue','21','\n\nWed','22','\n\nThu','23','\n\nFri','24','\n\nSat','25','\n\nSun','26','\n\nMon','27','\n\nTue','28','\n\nWed','29','\n\nThu','30','\n\nFri','31','\n\nSat']
tick_locations = np.arange(31)
plt.figure(figsize=(15,8))
plt.xticks(tick_locations, tick_labels)
plt.plot('DAY','SWST',data=data,linewidth=2,color="k")
plt.plot('DAY','WMID',data=data,linewidth=2,color="m")
plt.xlabel('DAY', fontsize=20)
plt.ylabel('VOLUME', fontsize=20)
plt.legend()
plt.show()
The pyplot function you are looking for is plt.xticks(). This is essentially a combination of ax.set_xticks() and ax.set_xticklabels()
From the documentation:
Parameters:
ticks : array_like
A list of positions at which ticks should be placed. You can pass an
empty list to disable xticks.
labels:
array_like, optional A list of explicit labels to place at the given
locs.
You would want something like the below code. Note you should probably explicitly set the tick locations as well as the labels to avoid setting labels in the wrong positions:
tick_labels = ['1','\n\nThu','2',..., '31','\n\nSat')
plt.xticks(tick_locations, tick_labels)
Note that the object-orientated API (i.e. using ax.) allows for more customisable plots.
Update
After the edit, I see that the labels you want to go below are part of the same list. Therefore your label list actually has a length of 62. So you need to join every 2 elements of your list together:
tick_labels=['1','\n\nThu','2','\n\nFri','3','\n\nSat','4','\n\nSun','5','\n\nMon','6','\n\nTue','7','\n\nWed','8',
'\n\nThu','9','\n\nFri','10','\n\nSat','11','\n\nSun','12','\n\nMon','13','\n\nTue','14','\n\nWed','15',
'\n\nThu','16','\n\nFri','17','\n\nSat','18','\n\nSun','19','\n\nMon','20','\n\nTue','21','\n\nWed','22',
'\n\nThu','23','\n\nFri','24','\n\nSat','25','\n\nSun','26','\n\nMon','27','\n\nTue','28','\n\nWed','29',
'\n\nThu','30','\n\nFri','31','\n\nSat']
tick_locations = np.arange(31)
new_labels = [ ''.join(x) for x in zip(tick_labels[0::2], tick_labels[1::2]) ]
plt.figure(figsize=(15, 8))
plt.xticks(tick_locations, new_labels)
plt.show()
Never use ax.set_xticklabels without setting the locations of the ticks as well. This can be done via ax.set_xticks.
ax.set_xticks(...)
ax.set_xticklabels(...)
Of course you may do the same with pyplot
ax = plt.gca()
ax.set_xticks(...)
ax.set_xticklabels(...)
I am plotting with seaborn a series of boxplots with
sns.boxplot(full_array)
where full_array contains 200 arrays.
Therefore, I have 200 boxplots and ticks on the x-axis from 0 to 200.
The xticks are too close to each other and I would like to show only some of them, for instance, a labeled xtick every 20, or so.
I tried several solutions as those mentioned here but they did not work.
Every time I sample the xticks, I get wrong labels for the ticks, as they get numbered from 0 to N, with unit spacing.
For instance, with the line ax.xaxis.set_major_locator(ticker.MultipleLocator(20))
I get a labelled xtick every 20 but the labels are 1, 2, 3, 4 instead of 20, 40, 60, 80...
Thanks to anyone who's so kind to help.
The seaborn boxplot uses a FixedLocator and a FixedFormatter, i.e.
print ax.xaxis.get_major_locator()
print ax.xaxis.get_major_formatter()
prints
<matplotlib.ticker.FixedLocator object at 0x000000001FE0D668>
<matplotlib.ticker.FixedFormatter object at 0x000000001FD67B00>
It's therefore not sufficient to set the locator to a MultipleLocator since the ticks' values would still be set by the fixed formatter.
Instead you would want to set a ScalarFormatter, which sets the ticklabels to correspond to the numbers at their position.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn.apionly as sns
import numpy as np
ax = sns.boxplot(data = np.random.rand(20,30))
ax.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
plt.show()
I have two subplots that share the same x-axis. I removed the xticklabels of the upper subplot, but the offset "1e7" remains visible. How can I hide it?
Here is the code I used :
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
s1 = plt.subplot(2,1,1)
s1.plot(np.arange(0,1e8,1e7),np.arange(10))
s1.tick_params(axis="x", labelbottom=False)
s2 = plt.subplot(2,1,2, sharex=s1)
s2.plot(np.arange(0,1e8,1e7),np.arange(10))
I also tried s1.get_xaxis().get_major_formatter().set_useOffset(False), but it did nothing and I also tried s1.get_xaxis().get_major_formatter().set_powerlimits((-9,9)) but it impacted also the lower suplot.
An alternative is to use plt.subplots to create the subplots, and use sharex=True as an option there. This automatically turns off all ticklabels and the offset_text from the top subplot. From the docs:
sharex : string or bool
If True, the X axis will be shared amongst all subplots. If True and
you have multiple rows, the x tick labels on all but the last row of
plots will have visible set to False
import matplotlib.pyplot as plt
import numpy as np
fig, (s1, s2) = plt.subplots(2, 1, sharex=True)
s1.plot(np.arange(0,1e8,1e7),np.arange(10))
s2.plot(np.arange(0,1e8,1e7),np.arange(10))
plt.show()
I finally find the answer on https://github.com/matplotlib/matplotlib/issues/4445. I need to add the following line to my code :
plt.setp(s1.get_xaxis().get_offset_text(), visible=False)
If I create a plot with matplotlib using the following code:
import numpy as np
from matplotlib import pyplot as plt
xx = np.arange(0,5, .5)
yy = np.random.random( len(xx) )
plt.plot(xx,yy)
plt.imshow()
I get a result that looks like the attached image. The problem is the
bottom-most y-tick label overlaps the left-most x-tick label. This
looks unprofessional. I was wondering if there was an automatic
way to delete the bottom-most y-tick label, so I don't have
the overlap problem. The fewer lines of code, the better.
In the ticker module there is a class called MaxNLocator that can take a prune kwarg.
Using that you can remove the first tick:
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
import numpy as np
xx = np.arange(0,5, .5)
yy = np.random.random( len(xx) )
plt.plot(xx,yy)
plt.gca().xaxis.set_major_locator(MaxNLocator(prune='lower'))
plt.show()
Result:
You can pad the ticks on the x-axis:
ax.tick_params(axis='x', pad=15)
Replace ax with plt.gca() if you haven't stored the variable ax for the current figure.
You can also pad both the axes removing the axis parameter.
A very elegant way to fix the overlapping problem is increasing the padding of the x- and y-tick labels (i.e. the distance to the axis). Leaving out the corner most label might not always be wanted. In my opinion, in general it looks nice if the labels are a little bit farther from the axis than given by the default configuration.
The padding can be changed via the matplotlibrc file or in your plot script by using the commands
import matplotlib as mpl
mpl.rcParams['xtick.major.pad'] = 8
mpl.rcParams['ytick.major.pad'] = 8
Most times, a padding of 6 is also sufficient.
This is answered in detail here. Basically, you use something like this:
plt.xticks([list of tick locations], [list of tick lables])