You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Matplotlib快速绘制带日期的Hovmöller图或热力图?

生成带时间/经度分箱的Hovmöller图(日期轴热力图)

针对你需要的时间-经度分箱热力图(Hovmöller图),这里提供三种无需手动写复杂分箱逻辑的简便方案,适配大量日期(如5500+)的场景:

方案一:Pandas + Seaborn(最易上手)

利用Pandas的分组/分箱函数快速统计频次,再用Seaborn绘制热力图,自动处理日期轴:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter

# 1. 构造数据框:替换成你的dates和lons列表
df = pd.DataFrame({
    'date': pd.to_datetime(dates),  # 自动解析日期字符串
    'lon': lons
})

# 2. 经度分箱:按1度间隔划分(范围可根据你的数据调整)
lon_bins = pd.interval_range(start=-180, end=180, freq=1)
df['lon_center'] = pd.cut(df['lon'], bins=lon_bins).apply(lambda x: x.mid)  # 用分箱中心值做标签

# 3. 时间分箱:按需求设置频率,比如每周('W')、每月('M')、10天('10D')
time_freq = 'W'  # 可根据可视化清晰度调整
heatmap_data = df.pivot_table(
    index=pd.Grouper(key='date', freq=time_freq),
    columns='lon_center',
    values='lon',
    aggfunc='count',  # 统计每个分箱的样本数,可换成mean等其他统计量
    fill_value=0
)

# 4. 绘制热力图
plt.figure(figsize=(12, 8))
sns.heatmap(heatmap_data.T, cmap='viridis', cbar_kws={'label': '样本数量'})
# 格式化日期轴,避免重叠
plt.gca().xaxis.set_major_formatter(DateFormatter('%Y-%m'))
plt.xlabel('时间')
plt.ylabel('经度 (°)')
plt.title('时间-经度Hovmöller图')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

关键说明:

  • 时间分箱的freq参数完全自定义,5500个日期按周分箱会得到约780个时间区间,显示足够清晰且可扩展到更多日期。
  • 若需要自定义时间分箱范围,可替换为pd.date_range生成固定间隔的时间箱,再用pd.cut分组。

方案二:Matplotlib hist2d(直接解决日期轴报错问题)

核心思路是把日期转成数值型(自起始日的天数)分箱,再转回日期格式显示,解决hist2d的日期兼容问题:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, num2date
import pandas as pd

# 1. 预处理数据
df = pd.DataFrame({'date': pd.to_datetime(dates), 'lon': lons})
# 日期转数值:将datetime转为自1970-01-01的天数
date_nums = df['date'].view('int64') // (10**9 * 86400)

# 2. 设置分箱参数
time_bin_width = 7  # 时间分箱宽度(天),比如7天=1周
lon_bin_width = 1   # 经度分箱宽度(度)
time_bins = np.arange(date_nums.min(), date_nums.max() + time_bin_width, time_bin_width)
lon_bins = np.arange(-180, 181, lon_bin_width)

# 3. 绘制hist2d
plt.figure(figsize=(12, 8))
counts, xedges, yedges, im = plt.hist2d(
    date_nums, df['lon'],
    bins=[time_bins, lon_bins],
    cmap='viridis'
)

# 4. 把数值型x轴转回日期格式
plt.gca().set_xticks((xedges[:-1] + xedges[1:]) / 2)
plt.gca().set_xticklabels(num2date((xedges[:-1] + xedges[1:]) / 2 * 86400 * 10**9))
plt.gca().xaxis.set_major_formatter(DateFormatter('%Y-%m'))
plt.xlabel('时间')
plt.ylabel('经度 (°)')
plt.colorbar(im, label='样本数量')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

关键说明:

  • 这种方法绕过了hist2d对日期类型的不兼容,直接用数值分箱,再通过num2date转回日期格式化,适合习惯用Matplotlib原生绘图的场景。

进阶方案:Xarray(专业气象/时序数据工具)

如果你的数据是时序类,Xarray的plot.hovmoller是专门为这类图设计的,代码更简洁:

import xarray as xr
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter

# 1. 分箱统计
df = pd.DataFrame({'date': pd.to_datetime(dates), 'lon': lons})
df['time_bin'] = pd.Grouper(key='date', freq='W')
df['lon_bin'] = pd.cut(df['lon'], bins=np.arange(-180, 181, 1))
count_df = df.groupby(['time_bin', 'lon_bin']).count().reset_index()

# 2. 转成Xarray Dataset并绘图
ds = count_df.set_index(['time_bin', 'lon_bin'])['lon'].to_xarray()
ds.plot.hovmoller(x='time_bin', y='lon_bin', cmap='viridis', cbar_label='样本数量')
plt.gca().xaxis.set_major_formatter(DateFormatter('%Y-%m'))
plt.tight_layout()
plt.show()

内容的提问来源于stack exchange,提问作者Outis Nemo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:35:09