I would like to remove seconds from my x-axis labels as they are unnecessary.
Also I want to center align the tick labels instead of have them positioned to the left of the tick mark.
Any suggestions on how to do this?
Here is some of the code that I've used if this helps
fig=plt.figure()
ax=fig.add_subplot(111)
line1 = plot(table.index,table[data],color=colors[0])
fig.autofmt_xdate(rotation=0)
tickFormat = matplotlib.ticker.LinearLocator(numticks=5)
ax.xaxis.set_major_locator(tickFormat)
from matplotlib.dates import DateFormatter
formatter = DateFormatter('%H:%M')
plt.gcf().axes[0].xaxis.set_major_formatter(formatter)
Related
I'm having with my xticks on my plot.
I have an hh:mm:ss format data on my x vector, but the xticks label are just eating up space on my x vector.
I'm trying to use only major xticks which would show the x vector label on 5 minutes basis.
but, the label not showing correctly.
right now this is the code that i wrote:
# -*- coding: utf-8 -*-
from os import listdir
from os.path import isfile, join
import pandas as pd
from Common import common as comm
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
fp = FontProperties(fname="../templates/fonts/msgothic.ttc")
config = comm.configRead()
commonConf = comm.getCommonConfig(config)
peopleBhvConf = comm.getPeopleBhvConf(config)
files = [f for f in listdir(commonConf['resultFilePath']) if isfile(join(commonConf['resultFilePath'], f))]
waitTimeGraphInput = [s for s in files if peopleBhvConf['resultFileName'] in s]
waitTimeGraphFile = commonConf['inputFilePath'] + waitTimeGraphInput[0]
waitTimeGraph = pd.read_csv(waitTimeGraphFile)
# Create data
N = len(waitTimeGraph.index)
x = waitTimeGraph['ホール入時間']
y = waitTimeGraph['滞留時間(出-入sec)']
xTicks = pd.date_range(min(x), max(x), freq="5min")
fig, ax = plt.subplots()
ax.scatter(x, y)
ax.set_xticklabels(xTicks, rotation='vertical')
plt.axhline(y=100, xmin=min(x), xmax=max(x), linewidth=2, color = 'red')
plt.setp(ax.get_xticklabels(), visible=True, rotation=30, ha='right')
plt.savefig(commonConf['resultFilePath'] + '1人1人の待ち時間分布.png')
plt.show()
and this is the result:
as you can see, the labels are still being printed only on the front of my plotting.
I'm expecting it would being printed on my major xticks position only.
The problem
If I understand correctly what is going on, xTicks array is shorter than x, am I right? If so, this is the issue.
I don't see in your code where you set the tick position, but I guess you are showing all of them, one per each element of x. But since you set the tick labels manually with ax.set_xticklabels(xTicks, rotation='vertical'), matplotlib has no way to know at which ticks those labels should go, hence it fills the first available ticks, and if there are more ticks, they are left without labels.
If you were able to read the labes, you would see that the written dates do not correspond to the labelled positions on the axis.
How to fix it
The general rule, be sure when you set tick labels manually, that the array containing the label has the same length of the array of the ticks. Add empty strings for the ticks where you do not want to have a labels.
However, since you spoke of major ticks and minor ticks, I show you how to set them in your case, where you have dates on the x axis.
Drop the xTicks, is not needed. Don't set the tick labels manually, hence don't use ax.set_xticklabels().
Your code should be:
fig, ax = plt.subplots()
ax.scatter(x, y)
plt.axhline(y=100, xmin=min(x), xmax=max(x), linewidth=2, color = 'red')
ax.xaxis.set_major_locator(MinuteLocator(interval=5))
ax.xaxis.set_minor_locator(MinuteLocator(interval=1))
ax.xaxis.set_major_formatter(DateFormatter('%H:%M:%S'))
plt.setp(ax.get_xticklabels(), visible=True, rotation=30, ha='right')
plt.savefig(commonConf['resultFilePath'] + '1人1人の待ち時間分布.png')
Remember to import the locator and formatter:
from matplotlib.dates import MinuteLocator, DateFormatter
A brief explanation: MinuteLocator finds each minute interval in your x axis and place a tick. The parameter interval allows you to set a tick each N minutes. So in the above code a major tick is placed each 5 minutes, a minor tick each minute.
DateFormatter simply format the date accordingly to the string (here I choose the format hour, minute, second). Note that no formatter has been set for minor ticks, so by default matplotlib uses the null formatter (no labels for minor ticks).
Here the documentation on the dates module of matplotlib.
To give you an idea of the result, here is an image I created using the code above with random data (just look at the x axis).
I'm trying to plot electricity usage against time. I'm using this script:
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
timelist = []
valuelist = []
# Logic that populates timelist and valuelist
timeaxis = np.array(timelist)
valueaxis = np.array(valuelist)
plt.plot(timeaxis, valueaxis, 'r-')
plt.savefig('elec_use.png', bbox_inches='tight')
plt.show()
The x-axis labels in the plot I get running the program above is all crammed into the length of the graph.
I tried rotating the labels by adding xticks like so:
plt.xticks(timeaxis, rotation=90)
This causes the labels to get trimmed.
How can I fix the problem? I have tried adding plt.gcf().subplots_adjust(bottom=0.25) but this does not fix the labels, it merely increases the real estate to the bottom of the graph. I want the x-axis labels to say Jun 02 2016 or simply Jun 02. I don't mind the graph being wide. Thanks in advance for any help.
You could use gcf().autofmt_xdate to format the x-axis nicely. And for the date string format, you could use matplotlib.dates.DateFormatter. It will be something like below:
So you code will be something like this:
fig, ax = plt.subplots(1)
timelist = []
valuelist = []
# Logic that populates timelist and valuelist
timeaxis = np.array(timelist)
valueaxis = np.array(valuelist)
ax.plot(timeaxis, valueaxis, 'r-')
# rotate and align the tick labels so they look better
fig.autofmt_xdate()
# use a more precise date string for the x axis locations in the
# toolbar
import matplotlib.dates as mdates
ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')
plt.savefig('elec_use.png', bbox_inches='tight')
plt.show()
I have a Pyplot plot, which I want to add gridlines to. I did this using:
plt.grid(True)
I then removed my x ticks using:
ax1.xaxis.set_visible(False)
My x ticks were removed, but so were the x grid lines. I would like them to stay.
Is there a way I can do this please?
Try this:
plt.grid(True)
ax.xaxis.set_ticklabels([])
It should work. The grid will be intact, but there won't be any tick labels. If you don't want the ticks too, add:
ax.xaxis.set_ticks_position('none')
from matplotlib.ticker import NullFormatter
ax.xaxis.set_major_formatter(NullFormatter())
This seems like it should be easy - but I can't see how to do it:
I have a plot with time on the X-axis. I want to set two sets of ticks, minor ticks showing the hour of the day and major ticks showing the day/month. So I do this:
# set date ticks to something sensible:
xax = ax.get_xaxis()
xax.set_major_locator(dates.DayLocator())
xax.set_major_formatter(dates.DateFormatter('%d/%b'))
xax.set_minor_locator(dates.HourLocator(byhour=range(0,24,3)))
xax.set_minor_formatter(dates.DateFormatter('%H'))
This labels the ticks ok, but the major tick labels (day/month) are drawn on top of the minor tick labels:
How do I force the major tick labels to get plotted below the minor ones? I tried putting newline escape characters (\n) in the DateFormatter, but it is a poor solution as the vertical spacing is not quite right.
Any advice would be appreciated!
You can use axis method set_tick_params() with the keyword pad. Compare following example.
import datetime
import random
import matplotlib.pyplot as plt
import matplotlib.dates as dates
# make up some data
x = [datetime.datetime.now() + datetime.timedelta(hours=i) for i in range(100)]
y = [i+random.gauss(0,1) for i,_ in enumerate(x)]
# plot
plt.plot(x,y)
# beautify the x-labels
plt.gcf().autofmt_xdate()
ax = plt.gca()
# set date ticks to something sensible:
xax = ax.get_xaxis()
xax.set_major_locator(dates.DayLocator())
xax.set_major_formatter(dates.DateFormatter('%d/%b'))
xax.set_minor_locator(dates.HourLocator(byhour=range(0,24,3)))
xax.set_minor_formatter(dates.DateFormatter('%H'))
xax.set_tick_params(which='major', pad=15)
plt.show()
PS: This example is borrowed from moooeeeep
Here's how the above snippet would render:
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])