I am working with satellite data with which I extract velocities of points over several decades. I have a dataframe with datetime index, and my velocities in columns (each column represents 1 point). The database is widely incomplete, and the points do not necessarily have values at the same time as the others.
I plotted a heatmap with seaborn which works, but the datetime displays too much information (I only want "YYYY-MM-DD". However when I compute the line ax.yaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d') ) the dates are not correct anymore. How can I solve this issue ?
(The second plot shows how it is correctly displayed when the DateFormatter line is commented out).
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
import seaborn as sns
import matplotlib.dates as mdates
v1 = np.array([1671., 1756., 1704., 1574., 1589., 1772., 1652., 1778., 1719.,
1699.], dtype=float)
dv1 = np.array(['2015-01-21T00:00:00.032000000', '2015-01-29T00:00:00.016000000',
'2014-06-11T00:00:00.544000000', '2014-12-20T00:00:00.160000000',
'2014-12-28T00:00:00.144000000', '2015-01-05T00:00:00.192000000',
'2014-07-29T00:00:00.512000000', '2015-03-02T00:00:00.080000256',
'2015-07-08T00:00:00.112000000', '2015-08-25T00:00:00.272000000'],
dtype='datetime64[ns]')
v2 = np.array([1647., 1758., 1722.], dtype=float)
dv2 = np.array(['2015-08-10T00:00:00.032000000', '2015-02-18T00:00:00.016000000',
'2014-09-19T00:00:00.544000000'],
dtype='datetime64[ns]')
df1 = pd.DataFrame({'Velocity0': v1}, index=pd.to_datetime(dv1))
df2 = pd.DataFrame({'Velocity1': v2}, index=pd.to_datetime(dv2))
df1 = df1.append(df2)
df1 = df1.sort_index()
df1 = df1.sort_index()
plt.figure(figsize=(15,15))
ax = sns.heatmap(df1)
for item in ax.get_yticklabels():
item.set_rotation(0)
for item in ax.get_xticklabels():
item.set_rotation(90)
ax.yaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d') )
plt.figure(figsize=(15,15))
plt.rcParams.update({'font.size': 20})
plt.plot(df1)

For the mdates DateFormatter to work you would need to have a continuous time scale on the y-axis based on matplotlib date units. The problem is that the x and y-axis of seaborn heatmaps use ranges of integers. You can check the y-axis units by printing the tick locations:
print(ax.get_yticks())
# [ 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5 10.5 11.5 12.5]
This is why the DateFormatter has no effect. Instead, you can format the labels by using the strftime method with the DatetimeIndex:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import seaborn as sns # v 0.11.0
v1 = np.array([1671., 1756., 1704., 1574., 1589., 1772., 1652., 1778., 1719., 1699.])
dv1 = np.array(['2015-01-21T00:00:00.032000000', '2015-01-29T00:00:00.016000000',
'2014-06-11T00:00:00.544000000', '2014-12-20T00:00:00.160000000',
'2014-12-28T00:00:00.144000000', '2015-01-05T00:00:00.192000000',
'2014-07-29T00:00:00.512000000', '2015-03-02T00:00:00.080000256',
'2015-07-08T00:00:00.112000000', '2015-08-25T00:00:00.272000000'],
dtype='datetime64[ns]')
v2 = np.array([1647., 1758., 1722.], dtype=float)
dv2 = np.array(['2015-08-10T00:00:00.032000000', '2015-02-18T00:00:00.016000000',
'2014-09-19T00:00:00.544000000'],
dtype='datetime64[ns]')
df1 = pd.DataFrame({'Velocity0': v1}, index=dv1)
df2 = pd.DataFrame({'Velocity1': v2}, index=dv2)
df1 = df1.append(df2).sort_index()
ax = sns.heatmap(df1)
ax.figure.set_size_inches(6,6)
ticklabels = [df1.index[int(tick)].strftime('%Y-%m-%d') for tick in ax.get_yticks()]
ax.set_yticklabels(ticklabels);

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With