I am trying to change the formatting of the x-axis into %H:%M, while the xticklabel all became 00:00. The xs looks like follows:
[datetime.time(15, 8, 35), datetime.time(15, 8, 36), datetime.time(15, 8, 37)]
I tried with the following script:
import matplotlib.dates as mdate
import matplotlib.pyplot as plt
dates = ['15:08:35', '15:08:36', '15:08:37']
xs = [datetime.strptime(d, '%H:%M:%S').time() for d in dates]
ys = range(len(xs))
plt.gca().xaxis.set_major_formatter(mdate.DateFormatter('%H:%M'))
plt.gca().xaxis.set_major_locator(mdate.DayLocator())
# Plot
plt.plot(xs, ys)
plt.gcf().autofmt_xdate()
plt.show()
And the image looks like this:
Please click
How could I change xticklabel into my desired formatting?
Matplotlib can handle datetime-objects easier than time objects. You can remove .time(). This code should work, I edited the dates to show changing x-values on the axis.
import matplotlib.dates as mdate
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
dates = ["15:05:35", "16:08:36", "17:09:37"]
# remove .time() from strptime
xs = [datetime.strptime(d, "%H:%M:%S") for d in dates]
ys = range(len(xs))
plt.gca().xaxis.set_major_formatter(mdate.DateFormatter("%H:%M"))
plt.gca().xaxis.set_major_locator(mdate.DayLocator())
# show all x-values on the x-axis
plt.xticks(xs)
# Plot
plt.plot(xs, ys)
plt.show()
Related
I have a dataframe and I want to show them on graph. When I start my code, the x and y axis are non-sequential. How can I solve it? Also I give a example graph on picture. First image is mine, the second one is what I want.
This is my code:
from datetime import timedelta, date
import datetime as dt #date analyse
import matplotlib.pyplot as plt
import pandas as pd #read file
def daterange(date1, date2):
for n in range(int ((date2 - date1).days)+1):
yield date1 + timedelta(n)
tarih="01-01-2021"
tarih2="20-06-2021"
start=dt.datetime.strptime(tarih, '%d-%m-%Y')
end=dt.datetime.strptime(tarih2, '%d-%m-%Y')
fg=pd.DataFrame()
liste=[]
tarih=[]
for dt in daterange(start, end):
dates=dt.strftime("%d-%m-%Y")
with open("fng_value.txt", "r") as filestream:
for line in filestream:
date = line.split(",")[0]
if dates == date:
fng_value=line.split(",")[1]
liste.append(fng_value)
tarih.append(dates)
fg['date']=tarih
fg['fg_value']=liste
print(fg.head())
plt.subplots(figsize=(20, 10))
plt.plot(fg.date,fg.fg_value)
plt.title('Fear&Greed Index')
plt.ylabel('Fear&Greed Data')
plt.xlabel('Date')
plt.show()
This is my graph:
This is the graph that I want:
Line plot with datetime x axis
So it appears this code is opening a text file, adding values to either a list of dates or a list of values, and then making a pandas dataframe with those lists. Finally, it plots the date vs values with a line plot.
A few changes should help your graph look a lot better. A lot of this is very basic, and I'd recommend reviewing some matplotlib tutorials. The Real Python tutorial is a good starting place in my opinion.
Fix the y axis limit:
plt.set_ylim(0, 100)
Use a x axis locator from mdates to find better spaced x label locations, it depends on your time range, but I made some data and used day locator.
import matplotlib.dates as mdates
plt.xaxis.set_major_locator(mdates.DayLocator())
Use a scatter plot to add data points as on the linked graph
plt.scatter(x, y ... )
Add a grid
plt.grid(axis='both', color='gray', alpha=0.5)
Rotate the x tick labels
plt.tick_params(axis='x', rotation=45)
I simulated some data and plotted it to look like the plot you linked, this may be helpful for you to work from.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.dates as mdates
fig, ax = plt.subplots(figsize=(15,5))
x = pd.date_range(start='june 26th 2021', end='july 25th 2021')
rng = np.random.default_rng()
y = rng.integers(low=15, high=25, size=len(x))
ax.plot(x, y, color='gray', linewidth=2)
ax.scatter(x, y, color='gray')
ax.set_ylim(0,100)
ax.grid(axis='both', color='gray', alpha=0.5)
ax.set_yticks(np.arange(0,101, 10))
ax.xaxis.set_major_locator(mdates.DayLocator())
ax.tick_params(axis='x', rotation=45)
ax.set_xlim(min(x), max(x))
I am trying to plot information against dates. I have a list of dates in the format "01/02/1991".
I converted them by doing the following:
x = parser.parse(date).strftime('%Y%m%d'))
which gives 19910102
Then I tried to use num2date
import matplotlib.dates as dates
new_x = dates.num2date(x)
Plotting:
plt.plot_date(new_x, other_data, fmt="bo", tz=None, xdate=True)
But I get an error. It says "ValueError: year is out of range". Any solutions?
You can do this more simply using plot() instead of plot_date().
First, convert your strings to instances of Python datetime.date:
import datetime as dt
dates = ['01/02/1991','01/03/1991','01/04/1991']
x = [dt.datetime.strptime(d,'%m/%d/%Y').date() for d in dates]
y = range(len(x)) # many thanks to Kyss Tao for setting me straight here
Then plot:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator())
plt.plot(x,y)
plt.gcf().autofmt_xdate()
Result:
I have too low reputation to add comment to #bernie response, with response to #user1506145. I have run in to same issue.
The answer to it is an interval parameter which fixes things up
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import datetime as dt
np.random.seed(1)
N = 100
y = np.random.rand(N)
now = dt.datetime.now()
then = now + dt.timedelta(days=100)
days = mdates.drange(now,then,dt.timedelta(days=1))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=5))
plt.plot(days,y)
plt.gcf().autofmt_xdate()
plt.show()
As #KyssTao has been saying, help(dates.num2date) says that the x has to be a float giving the number of days since 0001-01-01 plus one. Hence, 19910102 is not 2/Jan/1991, because if you counted 19910101 days from 0001-01-01 you'd get something in the year 54513 or similar (divide by 365.25, number of days in a year).
Use datestr2num instead (see help(dates.datestr2num)):
new_x = dates.datestr2num(date) # where date is '01/02/1991'
Adapting #Jacek Szałęga's answer for the use of a figure fig and corresponding axes object ax:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import datetime as dt
np.random.seed(1)
N = 100
y = np.random.rand(N)
now = dt.datetime.now()
then = now + dt.timedelta(days=100)
days = mdates.drange(now,then,dt.timedelta(days=1))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(days,y)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=5))
ax.tick_params(axis='x', labelrotation=45)
plt.show()
I have written the code below to visualise a joyplot. When trying to change the x axis labels using axes.set_xticks, I get the error: AttributeError: 'list' object has no attribute 'set_xticks'
import joypy
import pandas as pd
from matplotlib import pyplot as plt
data = pd.DataFrame.from_records([['twitter', 1],
['twitter', 6],
['wikipedia', 1],
['wikipedia', 3],
['indymedia', 1],
['indymedia', 9]], columns=['platform','day'])
# Get number of days in the dataset
numdays = max(set(data['day'].tolist()))
# Generate date strings from a manually set start date
start_date = "2010-01-01"
dates = pd.date_range(start_date, periods=numdays)
dates = [str(date)[:-9] for date in dates]
fig, axes = joypy.joyplot(data,by="platform")
axes.set_xticks(range(numdays)); axes.set_xticklabels(dates)
plt.show()
The expected output should look something like the following but with the dates from dates as ticklabels.
Since joypy.joyplot(..) returns a tuple of figure, axes and axes should be list of axes, you probably want to set the labels for the last axes,
axes[-1].set_xticks(range(numdays))
axes[-1].set_xticklabels(dates)
To make date plots with python matplotlib do you should use plot_date function.
fig, ax = plt.subplots()
ax.plot_date(dates, data1, '-')
I put the complete example in pastebin, follow the link:
https://pastebin.com/sVPUZaeM
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
from random import randrange, random
from datetime import datetime
#generate date list
start_date = np.datetime64('2010-01-01').astype(datetime)
numdays = 10
dates = pd.date_range(start_date, periods=numdays)
#Generate data example
data1 = [(random()+idx)**1.2 for idx in range(len(dates))]
data2 = [(random()+idx)**1.5 for idx in range(len(dates))]
#plot
fig, ax = plt.subplots()
ax.plot_date(dates, data1, '-')
ax.plot_date(dates, data2, '-')
#set the label for x and y and title
plt.title('Matplot lib dates wc example')
plt.xlabel('Dates')
plt.ylabel('Random values example')
#date format
ax.fmt_xdata = DateFormatter('%Y%m%d')
ax.grid(True)
fig.autofmt_xdate()
plt.show()
Python version tested successfully: 2.7.12
This code generates: this follow plot
I'm trying to make a plot where the x-axis is time and the y-axis is a bar chart that will have the bars covering a certain time period like this:
______________
|_____________|
_____________________
|___________________|
----------------------------------------------------->
time
I have 2 lists of datetime values for the start and end of these times I'd like to have covered. So far I have
x = np.array([dt.datetime(2010, 1, 8, i,0) for i in range(24)])
to cover a 24-hour period. My question is then how do I set and plot my y-values to look like this?
You could use plt.barh:
import datetime as DT
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
start = [DT.datetime(2000,1,1)+DT.timedelta(days=i) for i in (2,0,3)]
end = [s+DT.timedelta(days=i) for s,i in zip(start, [15,7,10])]
start = mdates.date2num(start)
end = mdates.date2num(end)
yval = [1,2,3]
width = end-start
fig, ax = plt.subplots()
ax.barh(bottom=yval, width=width, left=start, height=0.3)
xfmt = mdates.DateFormatter('%Y-%m-%d')
ax.xaxis.set_major_formatter(xfmt)
# autorotate the dates
fig.autofmt_xdate()
plt.show()
yields
Take a look at this example:
import datetime as dt
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
x = []
d = dt.datetime(2013, 7, 4)
for i in range(30):
d = d+dt.timedelta(days=1)
x.append(d)
y = range(len(x))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator())
plt.gcf().autofmt_xdate()
plt.bar(x,y)
plt.show()
The code writes out dates on the x-axis in the plot, see the picture below. The problem is that the dates get clogged up, as seen in the picture. How to make matplotlib to only write out every fifth or every tenth coordinate?
You can specify an interval argument to the DateLocator as in the following. With e.g. interval=5 the locator places ticks at every 5th date. Also, place the autofmt_xdate() after the bar method to get the desired output.
import datetime as dt
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
x = []
d = dt.datetime(2013, 7, 4)
for i in range(30):
d = d+dt.timedelta(days=1)
x.append(d)
y = range(len(x))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=5))
plt.bar(x, y, align='center') # center the bars on their x-values
plt.title('DateLocator with interval=5')
plt.gcf().autofmt_xdate()
plt.show()
With interval=3 you will get a tick for every 3rd date: