如何使用 Seaborn 热图选择日期频率和显示日期
How to choose date frequency and day of display with Seaborn Heatmap
我有一个包含多个列和日期作为索引的 DataFrame。我使用 sns.heatmap
来绘制它,日期在 y 轴上。我想强制刻度线只显示每年的 10 月 1 日。我使用了@Ayrton Bourn 在 Date axis in heatmap seaborn 上给出的解决方案,它允许我更改刻度的频率,但不能更改在哪一天显示日期。
到目前为止,他的方法是唯一允许我选择 y-ticks 频率的方法。我尝试使用 mdates.YearLocator()
或 set_major_locator
但没有成功。
对于下面的代码,您是否有任何建议可以让我选择日期刻度的频率(每年)和显示的日期(例如,每个“200x-10-01”)?
import numpy as np
from datetime import date, datetime, timedelta
import pandas as pd
import seaborn as sns
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
from collections.abc import Iterable
from sklearn import linear_model
class AxTransformer:
def __init__(self, datetime_vals=False):
self.datetime_vals = datetime_vals
self.lr = linear_model.LinearRegression()
return
def process_tick_vals(self, tick_vals):
if not isinstance(tick_vals, Iterable) or isinstance(tick_vals, str):
tick_vals = [tick_vals]
if self.datetime_vals == True:
tick_vals = pd.to_datetime(tick_vals).astype(int).values
tick_vals = np.array(tick_vals)
return tick_vals
def fit(self, ax, axis='x'):
axis = getattr(ax, f'get_{axis}axis')()
tick_locs = axis.get_ticklocs()
tick_vals = self.process_tick_vals([label._text for label in axis.get_ticklabels()])
self.lr.fit(tick_vals.reshape(-1, 1), tick_locs)
return
def transform(self, tick_vals):
tick_vals = self.process_tick_vals(tick_vals)
tick_locs = self.lr.predict(np.array(tick_vals).reshape(-1, 1))
return tick_locs
def set_date_ticks(ax, start_date, end_date, axis='y', date_format='%Y-%m-%d', **date_range_kwargs):
dt_rng = pd.date_range(start_date, end_date, **date_range_kwargs)
ax_transformer = AxTransformer(datetime_vals=True)
ax_transformer.fit(ax, axis=axis)
getattr(ax, f'set_{axis}ticks')(ax_transformer.transform(dt_rng))
getattr(ax, f'set_{axis}ticklabels')(dt_rng.strftime(date_format))
ax.tick_params(axis=axis, which='both', bottom=True, top=False, labelbottom=True)
return ax
base = datetime(2000, 1, 1)
arr = np.array([base + timedelta(days=i) for i in range(366*3)])
val = np.random.rand(len(arr),3)
df = pd.DataFrame(val, index = arr)
f, ax = plt.subplots(figsize=(20,20))
ax = sns.heatmap(df, ax = ax)
set_date_ticks(ax, '2000-01-01', '2003-12-01', freq='1Y')
ax.format_ydata = mdates.DateFormatter('% Y')
plt.show()
我通过查看 Kwargs 找到了解决方案。
要选择显示的日期,唯一需要更改的是“freq =”(请参阅 here 频率的详细列表)。在我的例子中,为了显示每年 10 月 1 日,我只需要将开始日期更改为 10 月 1 日,并将频率指定为我希望每 12 个月的月初(结束日期无关紧要):
f, ax = plt.subplots(figsize=(20,20))
ax = sns.heatmap(df, ax = ax)
set_date_ticks(ax, '2000-10-01', '2004-10-01', freq='12MS')
ax.format_ydata = mdates.DateFormatter('% Y')
plt.show()
我有一个包含多个列和日期作为索引的 DataFrame。我使用 sns.heatmap
来绘制它,日期在 y 轴上。我想强制刻度线只显示每年的 10 月 1 日。我使用了@Ayrton Bourn 在 Date axis in heatmap seaborn 上给出的解决方案,它允许我更改刻度的频率,但不能更改在哪一天显示日期。
到目前为止,他的方法是唯一允许我选择 y-ticks 频率的方法。我尝试使用 mdates.YearLocator()
或 set_major_locator
但没有成功。
对于下面的代码,您是否有任何建议可以让我选择日期刻度的频率(每年)和显示的日期(例如,每个“200x-10-01”)?
import numpy as np
from datetime import date, datetime, timedelta
import pandas as pd
import seaborn as sns
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
from collections.abc import Iterable
from sklearn import linear_model
class AxTransformer:
def __init__(self, datetime_vals=False):
self.datetime_vals = datetime_vals
self.lr = linear_model.LinearRegression()
return
def process_tick_vals(self, tick_vals):
if not isinstance(tick_vals, Iterable) or isinstance(tick_vals, str):
tick_vals = [tick_vals]
if self.datetime_vals == True:
tick_vals = pd.to_datetime(tick_vals).astype(int).values
tick_vals = np.array(tick_vals)
return tick_vals
def fit(self, ax, axis='x'):
axis = getattr(ax, f'get_{axis}axis')()
tick_locs = axis.get_ticklocs()
tick_vals = self.process_tick_vals([label._text for label in axis.get_ticklabels()])
self.lr.fit(tick_vals.reshape(-1, 1), tick_locs)
return
def transform(self, tick_vals):
tick_vals = self.process_tick_vals(tick_vals)
tick_locs = self.lr.predict(np.array(tick_vals).reshape(-1, 1))
return tick_locs
def set_date_ticks(ax, start_date, end_date, axis='y', date_format='%Y-%m-%d', **date_range_kwargs):
dt_rng = pd.date_range(start_date, end_date, **date_range_kwargs)
ax_transformer = AxTransformer(datetime_vals=True)
ax_transformer.fit(ax, axis=axis)
getattr(ax, f'set_{axis}ticks')(ax_transformer.transform(dt_rng))
getattr(ax, f'set_{axis}ticklabels')(dt_rng.strftime(date_format))
ax.tick_params(axis=axis, which='both', bottom=True, top=False, labelbottom=True)
return ax
base = datetime(2000, 1, 1)
arr = np.array([base + timedelta(days=i) for i in range(366*3)])
val = np.random.rand(len(arr),3)
df = pd.DataFrame(val, index = arr)
f, ax = plt.subplots(figsize=(20,20))
ax = sns.heatmap(df, ax = ax)
set_date_ticks(ax, '2000-01-01', '2003-12-01', freq='1Y')
ax.format_ydata = mdates.DateFormatter('% Y')
plt.show()
我通过查看 Kwargs 找到了解决方案。 要选择显示的日期,唯一需要更改的是“freq =”(请参阅 here 频率的详细列表)。在我的例子中,为了显示每年 10 月 1 日,我只需要将开始日期更改为 10 月 1 日,并将频率指定为我希望每 12 个月的月初(结束日期无关紧要):
f, ax = plt.subplots(figsize=(20,20))
ax = sns.heatmap(df, ax = ax)
set_date_ticks(ax, '2000-10-01', '2004-10-01', freq='12MS')
ax.format_ydata = mdates.DateFormatter('% Y')
plt.show()