Annotate date on the xaxis - python-3.x

I have the following code:
import pandas as pd
from pandas_datareader import data as web
import matplotlib.pyplot as plt
import datetime as datetime
start = datetime.date(2008,1,1)
end = datetime.date.today()
start1 = datetime.date(2019,1,1)
data = web.get_data_yahoo("AAPL",start, end)
data1 = web.get_data_yahoo("AMZN", start1, end1)
ax = data.plot(y ="Close")
data1.plot(y = "Close", ax=ax)
The resulting chart looks like this:
How can i annotate the orange line which is AMZN so i can see the date. Is there a way a straight line could be drawn down and have its date shown on the xaxis?

If you plot the date sting on the x-axis I think you will get a clumpy result. What about adding a text notation to the side:
ax.text(start1, data1.Close[0], start1, ha='right', va='top', rotation=90)
Here's the complete code if you want to add a vertical line as well:
import pandas as pd
from pandas_datareader import data as web
import matplotlib.pyplot as plt
import datetime as datetime
start = datetime.date(2008,1,1)
end = datetime.date.today()
start1 = datetime.date(2019,1,1)
data = web.get_data_yahoo("AAPL",start, end)
data1 = web.get_data_yahoo("AMZN", start1, end)
ax = data.plot(y ="Close")
data1.plot(y = "Close", ax=ax)
ylims = ax.get_ylim()
ax.vlines(start1, ylims[0], data1.Close[0], linestyles='--')
ax.text(start1, data1.Close[0], start1, ha='right', va='top', rotation=90)
ax.set_ylim(ylims)

Related

How to show all dates in matplotlib from excel import?

I have a code in python 3.11 for a contour plot generating from an excel table using matplotlib. The result shows only first days of months on the x axis (for example 1.6.2022, 1.7.2022 ...). I want all days from the excel source table. Her's the code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize
import pandas as pd
import matplotlib.dates as mdates
# import data from excel file
df = pd.read_excel('temperature_data.xlsx', index_col=0)
# Assign columns to variables
time = df.columns
depth = df.index
temperature = df.to_numpy()
# Creating the graph
fig, ax = plt.subplots()
min_temp = temperature.min()
max_temp = temperature.max()
cs = plt.contourf(time, depth, temperature, levels=np.arange(round(min_temp), round(max_temp)+2, 2), cmap='coolwarm', vmin=min_temp, vmax=max_temp)
cs2 = plt.contour(time, depth, temperature, levels=np.arange(round(min_temp), round(max_temp)+2, 2), colors='black')
plt.gca().invert_yaxis()
plt.clabel(cs2, inline=1, fontsize=10, fmt='%d')
plt.title('Teplota vody [°C]')
plt.xticks(rotation=90, ha='right')
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y'))
#ax.set_xlim(df.index.min(), df.index.max())
#ax.set_xlabel('Time')
ax.set_ylabel('hloubka [m]')
norm = Normalize(vmin=min_temp, vmax=max_temp)
plt.colorbar(cs, cmap='coolwarm', norm=norm)
plt.show()
Thank you for your help.

Convert string to matplotlib date for plotting

I've been trying to convert string date into a format that can be plotted on a graph.
The code
import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates
import datetime
def graph_data():
fig=plt.figure()
ax1=plt.subplot2grid((1,1),(0,0))
stock_price_url = 'https://pythonprogramming.net/yahoo_finance_replacement'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source=source_code.split('\n')
print(len(split_source))
for line in split_source[1:]:
stock_data.append(line)
date,openn,closep,highp,lowp,openp,volume=np.loadtxt(stock_data,delimiter=',',unpack=True)
x = [datetime.strptime(d, '%Y-%m-%d') for d in date]
ax1.plot_date(x,closep,'-',linewidth=0.1)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Graph')
plt.show()
graph_data()
Any method of conversion just gives the same error
ValueError: could not convert string to float: '2017-07-26'
What method can I use to convert the string into date that can be plotted
Ther's nothing wrong with your code. The problem is with the data.
If you look at the data, you will find that from date to volume features your data is a string like this :
data = '2017-07-26,153.3500,153.9300,153.0600,153.5000,153.5000,12778195.00'.
That is the representation of a string.
So you need to do some preprocessing first. There may be various methods to do so.
I found this method helpful to me:
First, you have to remove the commas in data and replace them with spaces and then use the split function to convert data into a split format.
So, you need to make these changes in your code:
date = []
closep = []
for i in range(len(stock_data)):
temp = stock_data[i].replace(',', ' ').split()
date.append(temp[0])
closep.append(temp[2])
0 and two are the positions of date and closep in your dataset.
Now instead of 'x' and 'closep' as you have used in your plot method, use these 'date ' and 'closep' I just shared you via code.
One more thing is that the graph is having trouble with this big dataset I think.
So use date[0:100], closep[0:100] to try the plot for smaller dataset.
The complete code would look like this:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates
import datetime
def graph_data():
fig = plt.figure()
ax1 = plt.subplot2grid((1, 1), (0, 0))
stock_price_url =
'https://pythonprogramming.net/yahoo_finance_replacement'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source[1:]:
stock_data.append(line)
date = []
closep = []
for i in range(len(stock_data)):
temp = stock_data[i].replace(',', ' ').split()
date.append(temp[0])
closep.append(temp[2])
ax1.plot_date(date[0:100], closep[0:100], '-', linewidth=0.1)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Graph')
plt.show()
graph_data()
Hope this helps.

How to display (format) epoch to full date with datacursor in a time series?

I have a custom formatter function to display both the Y and X coordinates of each point in my plot. As the plot is a time series, my x Axis is made of dates, which is making it difficult for me to display the exact same date as the plot is showing.
My code:
%matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import matplotlib.dates as mdates
from matplotlib.dates import date2num
from dateutil import parser
from bokeh.plotting import figure
import sqlite3
from mpldatacursor import datacursor
import pandas as pd
import datetime as dt
from datetime import datetime
fig = plt.figure(figsize = (10,4))
ax1 = fig.add_subplot(111)
ax1.grid(True)
plt.ion()
def animate(i):
datas = []
dates = []
con = sqlite3.connect('edgedb')
c = con.cursor()
c.execute('SELECT data, timestamp FROM edgedata')
data = c.fetchall()
for row in data:
datas.append(pd.to_datetime(row[1], format = '%Y-%m-%d %H:%M:%S').time())
dates.append(float(row[0]))
ax1.clear()
ax1.plot_date(x = datas, y = dates, color = 'darkgreen', ls='-', marker='o')
ax1.set_xticks(datas)
plt.xticks(rotation=60, ha='right')
plt.subplots_adjust(bottom=0.30)
plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator())
#ax1.xaxis.set_major_formatter(mdates.DateFormatter('$H:%M:%S'))
ax1.grid(True)
plt.ion()
def print_coords(**kwargs):
return 'Valor medido : {y:.6f} às {x:s}'.format(y=kwargs['y'],
x=dt.datetime.fromtimestamp(kwargs['x']).strftime('%Y-%m-%d %H:%M:%S'))
datacursor(ax1, formatter = print_coords)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
This way, the cursor is displaying my Y value correctly, but my X comes as '1970-01-01 11:59:03' in the first point, increasing as it advances.
#edit:
As my friend Yuca called, I'm giving some points as they appear in my database.
(2.609698591082275, '2019-08-01 14:59:02')
(1.576077072171736, '2019-08-01 15:01:42')
(2.732782944225141, '2019-08-01 15:37:35')
(2.121527818052438, '2019-08-01 15:37:56')
(2.296660329191338, '2019-08-01 15:38:37')
(1.176709831423572, '2019-08-01 15:42:38')
(1.434814273623745, '2019-08-01 16:50:06')
(2.276750775178628, '2019-08-01 16:55:19')
Thanks in advance!

Having xticks to display Months in a Seaborn regplot with Pandas

I can not figure how to make the xticks to display Months.
For a reproducible example, my data is:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
json = '{"index":{"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16},"Date":{"0":1516147200000,"1":1516752000000,"2":1517788800000,"3":1520208000000,"4":1520985600000,"5":1522281600000,"6":1522886400000,"7":1523404800000,"8":1523491200000,"9":1524096000000,"10":1525305600000,"11":1525737600000,"12":1526428800000,"13":1527811200000,"14":1533686400000,"15":1534377600000,"16":1534809600000},"FB":{"0":0.978943931,"1":1.0282769543,"2":0.999118052,"3":0.994377665,"4":1.0152684601,"5":0.880773866,"6":0.8782934503,"7":0.91676777,"8":0.9032631287,"9":0.9265792518,"10":0.959210704,"11":0.9862198213,"12":1.0098114818,"13":1.0692867773,"14":1.0207253613,"15":0.962958874,"16":0.9514937543},"month":{"0":1,"1":1,"2":2,"3":3,"4":3,"5":3,"6":4,"7":4,"8":4,"9":4,"10":5,"11":5,"12":5,"13":6,"14":8,"15":8,"16":8}}'
toy_data = pd.read_json(json)
fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111)
ax.set_title('Share Price Facebook, Google and the SP500')
sns.regplot( x = 'index', y = 'FB', data = toy_data , label = 'FB', fit_reg = True)
plt.show()
I would like to ammend the code so that in the x axis appear the Months of the Range of Observations. That is the tick labels 0 and 1 would be replaced with 'Jan' (appearing once), the tick label 2 would be replaced with 'Feb', the tick labels 3, 4, 5 with 'March' (appearing once), etc.
You can convert your dates to numbers and use those numbers as the x input for the regplot. Then you can format your ticklabels as dates.
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns
json = '{"index":{"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16},"Date":{"0":1516147200000,"1":1516752000000,"2":1517788800000,"3":1520208000000,"4":1520985600000,"5":1522281600000,"6":1522886400000,"7":1523404800000,"8":1523491200000,"9":1524096000000,"10":1525305600000,"11":1525737600000,"12":1526428800000,"13":1527811200000,"14":1533686400000,"15":1534377600000,"16":1534809600000},"FB":{"0":0.978943931,"1":1.0282769543,"2":0.999118052,"3":0.994377665,"4":1.0152684601,"5":0.880773866,"6":0.8782934503,"7":0.91676777,"8":0.9032631287,"9":0.9265792518,"10":0.959210704,"11":0.9862198213,"12":1.0098114818,"13":1.0692867773,"14":1.0207253613,"15":0.962958874,"16":0.9514937543}}'
df = pd.read_json(json)
df["Date2"] = mdates.date2num(pd.to_datetime(df["Date"]))
fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111)
ax.set_title('Share Price Facebook, Google and the SP500')
sns.regplot( x = 'Date2', y = 'FB', data = df , label = 'FB', fit_reg = True, ax=ax)
loc = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(loc)
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))
plt.show()

How to plot events with minute precision on hourly plots using matplotlib?

I have an hourly plot generated with matplotlib. I need to plot an event which goes for example, from 09:00 to 10:45. When I try to do it, using axvspan I obtain a bar from 9:00 to 10:00. How could I obtain the longer one?
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import datetime as dt
import pandas as pd
now_date = dt.datetime(2018,10,1,9)
d_tw_ini = now_date - dt.timedelta(hours = 1)
d_tw_fin = now_date + dt.timedelta(hours = 3)
dts = pd.date_range(start=d_tw_ini, end=d_tw_fin, freq='1H', name='ini', closed='left')
data=pd.DataFrame({'val':[0.5,0.4,0.7,0.9]})
ev1=[dt.datetime(2018,10,1,9,5),dt.datetime(2018,10,1,10,50)]
data['t']=dts.values
data.set_index('t',inplace=True)
fig = plt.figure()
gs = GridSpec(1, 1)
ax_1 = fig.add_subplot(gs[0, 0])
data.plot(ax=ax_1, y='val')
ax_1.axvspan(ev1[0],ev1[1], alpha=0.3, color= 'red')
Result
Juan, it looks when you used pandas to plot, the hourly indexing seems to cause issues with how axvspan gets plotted.
I replaced
data.plot(ax=ax_1, y='val')
with
ax_1.plot(data.index, data['val'])
which generates the image below, but unfortunately you lose the automated x-axis formatting.
Adding the two lines below will result in the same date formatting as your example.
ax_1.set_xticks([x for x in data.index])
ax_1.set_xticklabels([str(x)[11:16] for x in data.index])
Below is the full code to produce the above plot.
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import datetime as dt
import pandas as pd
now_date = dt.datetime(2018,10,1,9)
d_tw_ini = now_date - dt.timedelta(hours = 1)
d_tw_fin = now_date + dt.timedelta(hours = 3)
dts = pd.date_range(start=d_tw_ini, end=d_tw_fin, freq='1h', name='ini',
closed='left')
data=pd.DataFrame({'val':[0.5,0.4,0.7,0.9]})
ev1=[dt.datetime(2018,10,1,9,5,0),dt.datetime(2018,10,1,10,50,0)]
data['t']=dts.values
data.set_index('t',inplace=True)
fig = plt.figure()
gs = GridSpec(1, 1)
ax_1 = fig.add_subplot(gs[0, 0])
# modified section below
ax_1.plot(data.index, data['val'])
ax_1.axvspan(ev1[0],ev1[1], alpha=0.3, color= 'red')
ax_1.set_xticks([x for x in data.index])
ax_1.set_xticklabels([str(x)[11:16] for x in data.index])
plt.show()

Resources