如何在Matplotlib中自定义热力图的X轴刻度与标签?
自定义热力图X轴标签与刻度样式
我正尝试自定义热力图的X轴标签与刻度,使其和之前创建的另一张图表样式一致。以下是我的实现代码:
import matplotlib as mplt from matplotlib import dates, pyplot from matplotlib.transforms import ScaledTranslation import numpy as np import pandas as pd import datetime s_names = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # categories dates_ = pd.date_range('2023/01/01', '2023/01/08', freq='3H', tz='utc') # Creating a list of date time for index. matrix = pd.DataFrame(columns=s_names, index=dates_) # initializing the df. matrix = matrix.applymap(lambda l: l if not np.isnan(l) else np.random.choice(range(1, 10))) # replacing nan in the df with random number. matrix.sort_values(by=matrix.index[0], ascending=True, axis=1, inplace=True) # Sorting by the first date (row), columns get ordered in from lowest to highest. params = {"ytick.color" : "b", "xtick.color" : "b", "axes.labelcolor" : "w", "axes.edgecolor" : "w"} pyplot.rcParams.update(params) fig, ax = pyplot.subplots(figsize = (14, 4)) ax = pyplot.gca(); extent = (0, matrix.shape[0], matrix.shape[1], 0) ax.imshow(matrix.transpose(), cmap=pyplot.cm.RdYlGn) ax.set_yticks(np.arange(len(s_names)), labels = list(matrix.columns)) ax.set_yticks(np.arange(-0.5, len(s_names),1), minor=True) ax.set_xticks(np.arange(-0.5, len(dates_),1), minor=True) pyplot.xticks(rotation=90) ax.set_aspect(1) ax.grid(color="w", linewidth=3, which='minor')
当前代码生成的热力图X轴效果:
我期望实现的X轴样式:
修改方案
要实现目标样式,核心是只在日期分界点显示主刻度标签,同时保留网格分隔每个时间段。修改后的完整代码如下:
import matplotlib as mplt from matplotlib import dates, pyplot import numpy as np import pandas as pd import datetime s_names = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 分类 dates_ = pd.date_range('2023/01/01', '2023/01/08', freq='3H', tz='utc') # 创建时间索引 matrix = pd.DataFrame(columns=s_names, index=dates_) # 初始化DataFrame # 填充随机数 matrix = matrix.applymap(lambda l: l if not np.isnan(l) else np.random.choice(range(1, 10))) # 按第一行排序列 matrix.sort_values(by=matrix.index[0], ascending=True, axis=1, inplace=True) # 设置全局参数 params = {"ytick.color" : "b", "xtick.color" : "b", "axes.labelcolor" : "w", "axes.edgecolor" : "w"} pyplot.rcParams.update(params) fig, ax = pyplot.subplots(figsize = (14, 4)) # 绘制热力图 ax.imshow(matrix.transpose(), cmap=pyplot.cm.RdYlGn) # Y轴设置 ax.set_yticks(np.arange(len(s_names)), labels = list(matrix.columns)) ax.set_yticks(np.arange(-0.5, len(s_names),1), minor=True) # -------------------------- 关键修改:X轴设置 -------------------------- # 1. 获取每天起始时刻对应的索引位置 daily_starts = dates_.to_series().groupby(dates_.date).first().index tick_positions = [dates_.get_loc(dt) for dt in daily_starts] # 2. 设置主刻度:只显示每天的日期标签 ax.set_xticks(tick_positions, labels=[dt.strftime('%Y-%m-%d') for dt in daily_starts]) # 3. 设置次要刻度:用于分隔每个3小时时间段,显示网格 ax.set_xticks(np.arange(-0.5, len(dates_), 1), minor=True) # 旋转X轴标签,优化可读性 pyplot.xticks(rotation=45) # 网格和比例设置 ax.set_aspect('auto') # 避免图形被过度压缩 ax.grid(color="w", linewidth=3, which='minor') pyplot.tight_layout() pyplot.show()
修改说明
- 提取每天的起始位置作为主刻度,仅显示日期标签,避免过多刻度重叠
- 保留次要刻度用于分隔每个3小时时间段,维持原有的白色网格线样式
- 将
set_aspect(1)改为set_aspect('auto'),防止热力图被压缩导致X轴拥挤 - 调整标签旋转角度为45度,比90度更易阅读
- 加入
tight_layout()优化整体布局,避免标签被截断
内容的提问来源于stack exchange,提问作者AGS
相关产品推荐
相关产品推荐

