I'm trying to have the tick labels of my Graph displayed fully, but I'm not getting the desired result, despite my efforts.
If I merely use autofmt_xdate(), the dates are correctly shown, but not for every data point plotted; however, if I force my x tick labels to be displayed by passing x by datetime objects to xtick(), It only seems to display the year.
fig1 = plt.figure(1)
# x is a list of datetime objects
plt.title('Portfolio Instruments')
plt.subplot(111)
plt.plot(x, y)
plt.xticks(fontsize='small')
plt.yticks([i * 5 for i in range(0, 15)])
fig1.autofmt_xdate()
plt.show()
Graph passing x to plt.xticks():
Graph without passing x to plt.xticks()
Where's my mistake? I can't find it.
Question
How do I plot all of my data points of x and format it to show the entire datetime object I'm passing the graph using autofmt_xdate()?
I have a list of datetime objects which I want to pass as the x values of my plot.
Pass the dates you want ticks at to xticks, and then set the major formatter for the x axis, using plt.gca().xaxis.set_major_formatter:
You can then use the DateFormatter from matplotlib.dates, and use a strftime format string to get the format in your question:
import matplotlib.dates as dates
fig1 = plt.figure(1)
# x is a list of datetime objects
plt.title('Portfolio Instruments')
plt.subplot(111)
plt.plot(x, y)
plt.xticks(x,fontsize='small')
plt.gca().xaxis.set_major_formatter(dates.DateFormatter('%b %d %Y'))
plt.yticks([i * 5 for i in range(0, 15)])
fig1.autofmt_xdate()
plt.show()
Note: I created the data for the above plot using the code below, so x is just a list of datetime objects for each weekday in a month (i.e. without weekends).
import numpy as np
from datetime import datetime,timedelta
start = datetime(2016, 1, 1)
end = datetime(2016, 2, 1)
delta = timedelta(days=1)
d = start
weekend = set([5, 6])
x = []
while d <= end:
if d.weekday() not in weekend:
x.append(d)
d += delta
y = np.random.rand(len(x))*70
I'm pretty sure I had a similar problem, and the way I solved it was to use the following code:
def formatFig():
date_formatter = DateFormatter('%H:%M:%S') #change the format here to whatever you like
plt.gcf().autofmt_xdate()
ax = plt.gca()
ax.xaxis.set_major_formatter(date_formatter)
max_xticks = 10 # sets the number of x ticks shown. Change this to number of data points you have
xloc = plt.MaxNLocator(max_xticks)
ax.xaxis.set_major_locator(xloc)
def makeFig():
plt.plot(xList,yList,color='blue')
formatFig()
makeFig()
plt.show(block=True)
It is a pretty simple example but you should be able to transfer the formatfig() part to use in your code.
Related
So I've spent some time managing to plot data using time on the x-axis, and the way I've found to do that is to use matplotlib.plot_date after converting datetime objects to pltdates objects.
X_d = pltdates.date2num(X) # X is an array containing datetime objects
(...)
plt.plot_date(X_d, Y)
It works great, all my data is plotted properly.
Plot with dates appearing on x-axis
However, all the measures I want to plot were made the same day (17/12/2021), the only difference is the time.
As shown on the image, matplotlib still displays the number of the the day (17th) although it is the same within the whole plot.
Anyone has a clue how to keep only the time, still using matplotlib.plot_date?
Use this example:
import matplotlib
import matplotlib.pyplot as plt
from datetime import datetime
origin = ['2020-02-05 04:11:55',
'2020-02-05 05:01:51',
'2020-02-05 07:44:49']
a = [datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in origin]
b = ['35.764299', '20.3008', '36.94704']
x = matplotlib.dates.date2num(a)
formatter = matplotlib.dates.DateFormatter('%H:%M')
figure = plt.figure()
axes = figure.add_subplot(1, 1, 1)
axes.xaxis.set_major_formatter(formatter)
plt.setp(axes.get_xticklabels(), rotation=15)
axes.plot(x, b)
plt.show()
I'm having trouble limiting the number of dates on the x-axis to make them legible. I need to plot the word length vs the year but the number of years is too large for the plot size.
The Issue:
Any help is appreciated.
As mentioned in the comments, use datetime (if your dates are in string format, you can easily convert them to datetime). Once you do that it should automatically display years along the x-axis. If you need to change the frequency of ticks to every year (or anything else), you can use mdates, like so:
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import datetime
import math
start = datetime.datetime.strptime("01-01-2000", "%d-%m-%Y")
end = datetime.datetime.strptime("10-04-2019", "%d-%m-%Y")
x = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]
y = [math.sqrt(x) for x in range(len(x))]
fig, ax = plt.subplots()
ax.plot(x, y)
ax.xaxis.set_major_locator(mdates.YearLocator())
fig.autofmt_xdate()
plt.show()
The snippet above generates the following:
I have a large database containing about 1 million entries. In one column there are dates in this form: '%Y-%m-%d %H:%M:%S. There is one entry every second.
I can select the period I want to plot from the database, e.g
date1 = '2015-04-22 20:28:50'
date2 = '2015-04-23 21:42:09'
and the other column I want to plot in the Y axis.
As you can see in the specific example, from date1 to date2 it's about 86000 entries - or - points to plot.
Is there a way to plot efficiently these data using matplotlib, with the dates to show in the x axis?
Of course not all dates can be shown, but as the plotting period is dynamic (I insert into a web form the dates I want), is there a way to program it so that the plot will be the best possible every time?
So far, I can put all the dates in a list, and all the Y data in another list.
Below is my code so far, which plots the data but the X-axis labels are nothing near what I want.
from buzhug import Base
import datetime
import data_calculations as pd
import matplotlib.pyplot as plt
import matplotlib
import time
date1 = '2015-04-22 20:28:50'
date2 = '2015-04-24 19:42:09'
db = Base('monitor').open()
result_set = db.select(['MeanVoltage','time'],"time>=start and time<=stop", start=date1, stop=date2)
V = [float(record.MeanVoltage) for record in result_set]
Date = [str(record.time) for record in result_set]
dates = [datetime.datetime.strptime(record, '%Y-%m-%d %H:%M:%S') for record in Date]
dates = matplotlib.dates.date2num(dates)
fig, ax = plt.subplots()
ax.plot_date(dates, V)
plt.grid(True)
plt.show()
And the result is
Plot
Thank you in advance
Edit:
I have fixed the issue by adding these lines:
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y %H:%M:%S' ))
plt.gcf().autofmt_xdate()
However, now I want to pass the plot to a web server using the mpld3 plugin:
mpld3.plugins.get_plugins(fig)
mpld3.fig_to_html(fig)
mpld3.show()
While, without the plugin, the plot appears just fine, with the dates in the x axis, with the plugin it seems like it can't parse this line
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y %H:%M:%S' ))
into the html code and as a result the x axis label appears in unix time.
Anyone knows what's wrong with the plugin?
The problem is the large number of points (One every second is a bundle!). If you try to plot each point as a circle you will have these problems.
But it is easily solved by changing it to a line graph, changing:
ax.plot_date(dates, V, '-') # Where '-' means a line plot
For example:
# some sample data
x = np.linspace(0.1, np.pi, 86000)
y = np.cos(x)**2 * np.log(x)
plt.plot(x, y, 'o')
plt.plot(x, y, '-')
I have written code which plots the past seven day stock value for a user-determined stock market over time.
The problem I have is that I want to format the x axis in a YYMMDD format.
I also don't understand what 2.014041e7 means at the end of the x axis.
Values for x are:
20140421.0, 20140417.0, 20140416.0, 20140415.0, 20140414.0, 20140411.0, 20140410.0
Values for y are:
531.17, 524.94, 519.01, 517.96, 521.68, 519.61, 523.48
My code is as follows:
mini = min(y)
maxi = max(y)
minimum = mini - 75
maximum = maxi + 75
mini2 = int(min(x))
maxi2 = int(max(x))
plt.close('all')
fig, ax = plt.subplots(1)
pylab.ylim([minimum,maximum])
pylab.xlim([mini2,maxi2])
ax.plot(x, y)
ax.plot(x, y,'ro')
ax.plot(x, m*x + c)
ax.grid()
ax.plot()
When plotting your data using your method you are simply plotting your y data against numbers (floats) in x such as 20140421.0 (which I assume you wish to mean the date 21/04/2014).
You need to convert your data from these floats into an appropriate format for matplotlib to understand. The code below takes your two lists (x, y) and converts them.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime as dt
# Original data
raw_x = [20140421.0, 20140417.0, 20140416.0, 20140415.0, 20140414.0, 20140411.0, 20140410.0]
y = [531.17, 524.94, 519.01, 517.96, 521.68, 519.61, 523.48]
# Convert your x-data into an appropriate format.
# date_fmt is a string giving the correct format for your data. In this case
# we are using 'YYYYMMDD.0' as your dates are actually floats.
date_fmt = '%Y%m%d.0'
# Use a list comprehension to convert your dates into datetime objects.
# In the list comp. strptime is used to convert from a string to a datetime
# object.
dt_x = [dt.datetime.strptime(str(i), date_fmt) for i in raw_x]
# Finally we convert the datetime objects into the format used by matplotlib
# in plotting using matplotlib.dates.date2num
x = [mdates.date2num(i) for i in dt_x]
# Now to actually plot your data.
fig, ax = plt.subplots()
# Use plot_date rather than plot when dealing with time data.
ax.plot_date(x, y, 'bo-')
# Create a DateFormatter object which will format your tick labels properly.
# As given in your question I have chosen "YYMMDD"
date_formatter = mdates.DateFormatter('%y%m%d')
# Set the major tick formatter to use your date formatter.
ax.xaxis.set_major_formatter(date_formatter)
# This simply rotates the x-axis tick labels slightly so they fit nicely.
fig.autofmt_xdate()
plt.show()
The code is commented throughout so should be easily self explanatory. Details on the various modules can be found below:
datetime
matplotlib.dates
I have a trouble plotting data, I only want plot HH:MM:SS but the plot shows HH:MM:SS.sssss or HH:MM:SS.%f. Below i gonna detail what I did (matplotlib, numpy are already imported )
Method I
Loading files to plot
import datetime as dt
data=genfromtxt('27JAN12.K7O', delimiter=2*[4]+5*[2]+8*[7])
f245 = data[:, 7]
Generating array for time (1 data per second)
base = dt.datetime(2014,1,27,11,07,59)
time = array([base + dt.timedelta(seconds=i) for i in range(len(data))])
plot(time,f245)
When i did this, i got this plot (with innecesary precision)
here i got time like 18:15:00.000000 (i just like 18:15:00)
Method II
The same way to load data, in this case only I took the time of the data and coverted in time string
t = data[:,1] #in decimals e.g. 18,5 represents 18:30:00
tstr = map(str, [dt.timedelta(seconds=x) for x in t])
time = []
for i in tstr:
try:
time.append(dt.datetime.strptime(i, "%H:%M:%S"))
except ValueError:
time.append(dt.datetime.strptime(i, "%H:%M:%S.%f"))
plot(time,f245)
In this case, i got time like 18:15:00.%f
So, how i could repair this?
You should use plot_date to plot datetime objects using matplotlib.
You can use matplotlib.dates.date2num to convert the datetime objects into the matplotlib format.
Furthermore you can use DateFormatter objects to set the formatting of the x-axis tick labels.
I have now included a small example using generated data, hopefully this will explain everything for you.
import numpy as numpy
import matplotlib.pyplot as plt
from matplotlib.dates import date2num, DateFormatter
import datetime as dt
base = dt.datetime(2014, 1, 27, 11, 7, 59)
x = [base + dt.timedelta(seconds=i) for i in range(10)]
y = [i**2 for i in range(10)]
x = date2num(x) # Convert datetime objects to the correct format for matplotlib.
fig, ax = plt.subplots()
ax.plot_date(x, y) # Use plot_date rather than plot
# Set the xaxis major formatter as a DateFormatter object
# The string argument shows what format you want (HH:MM:SS)
ax.xaxis.set_major_formatter(DateFormatter('%H:%M:%S'))
# This simply makes them look pretty by setting them diagonal.
fig.autofmt_xdate()
plt.show()