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

如何用Matplotlib contourf复刻SAS生成的月-小时等高线图?

从SAS迁移至Python:等高线图数据处理与绘图修正

问题说明

正在从SAS迁移到Python,需要用Matplotlib的contourf生成与SAS输出一致的等高线图:

  • X轴为1-12月,Y轴为0、3、6...21点(步长3)
  • 数据存储在cigvis_df(Pandas DataFrame)中
  • 当前生成的图像效果与SAS不符,不确定如何正确处理DataFrame中的月份、小时数据对绘图矩阵的影响,虽尝试转置修正方向但效果仍不对,需确认数据处理与绘图逻辑。

现有代码

数据提取代码

cigvis3000_df = cigvis_df[['CIG3000V3']].copy()
z_data = cigvis3000_df.to_numpy()
x_axis = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y_axis = [0, 3, 6, 9, 12, 15, 18, 21]

完整绘图代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

cigvis3000_df = cigvis_df[['CIG3000V3']].copy()
z_data = cigvis3000_df.to_numpy()

plotcolors = 'white', '#FFFFB2', '#FED976', '#FEB24C', '#FD8D3C', '#F03B20', '#BD0026'

fig, ax = plt.subplots(figsize=(6, 4))

x_axis = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y_axis = [0, 3, 6, 9, 12, 15, 18, 21]

z2 = z_data.reshape((len(x_axis), len(y_axis)))

x, y = np.meshgrid(x_axis, y_axis)

# 语法错误:多了逗号和括号
img = plt.contourf(x, y, z2.T, origin='image', levels=np.arange(5, 50, 5), colors=plotcolors), 
extend='both')

plt.grid(b=True, which='both', color='gray', linestyle='dashdot')
yticks = [0, 3, 6, 9, 12, 15, 18, 21]
ax.set_yticks(yticks)
ax.set_ylabel('Hour (UTC)')

# 缺少ticker导入
positions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
labels = ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']
ax.xaxis.set_major_locator(ticker.FixedLocator(positions))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(labels))

plt.colorbar(mappable=plt.gci(), pad=.15, orientation='horizontal',extend='both', aspect=35)

plt.tight_layout()
plt.show()

原始DataFrame数据

MONTH,HOUR,CIG3000V3
1,0,23.1
1,3,22.6
1,6,24.6
1,9,26.2
1,12,27.3
1,15,27.7
1,18,26.7
1,21,26.3
2,0,20.8
2,3,18.2
2,6,19.6
2,9,20.3
2,12,24
2,15,26.4
2,18,26.1
2,21,22.8
3,0,20.3
3,3,20.7
3,6,23.4
3,9,24.6
3,12,28
3,15,29.1
3,18,26.5
3,21,20.6
4,0,16
4,3,15.6
4,6,15.9
4,9,18.3
4,12,21.3
4,15,24.9
4,18,21.9
4,21,17.7
5,0,11.2
5,3,11.8
5,6,18
5,9,21.4
5,12,24.1
5,15,26.1
5,18,19.8
5,21,11.7
6,0,3.2
6,3,3.8
6,6,4.6
6,9,6
6,12,10.5
6,15,9.6
6,18,8.4
6,21,4
7,0,3.5
7,3,2.1
7,6,2.2
7,9,4.3
7,12,5.3
7,15,6
7,18,5.4
7,21,3.7
8,0,4.1
8,3,4.2
8,6,6.2
8,9,8.8
8,12,12.5
8,15,12.7
8,18,10.3
8,21,5.5
9,0,5.7
9,3,6.4
9,6,9.3
9,9,10.9
9,12,16.5
9,15,15.3
9,18,12.3
9,21,8.6
10,0,14.3
10,3,14.8
10,6,16.9
10,9,18.9
10,12,21.2
10,15,19.6
10,18,18.4
10,21,15.8
11,0,13.9
11,3,14.1
11,6,14.8
11,9,14.7
11,12,15.7
11,15,17.7
11,18,17.2
11,21,13.2
12,0,22.6
12,3,24.2
12,6,26.4
12,9,26.4
12,12,28.8
12,15,29.5
12,18,27.3
12,21,26.3

修正方案

核心问题

原代码直接提取CIG3000V3列转成numpy后reshape,依赖数据的存储顺序,若顺序和SAS的矩阵排列逻辑不一致,就会导致图像错位。正确的做法是通过透视表明确映射月份、小时与数值的对应关系,保证矩阵结构完全匹配坐标轴维度。

修正步骤

  1. 生成透视表:将DataFrame转换为行=月份、列=小时的矩阵,确保每个位置的数值对应正确的月份和小时。
  2. 修正绘图参数:修复语法错误,调整origin参数匹配SAS的坐标方向,确保无需额外转置。
  3. 补充缺失导入:添加matplotlib.ticker的导入。

修正后的完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

# 生成透视表:行是月份,列是小时,值为CIG3000V3
pivot_df = cigvis_df.pivot(index='MONTH', columns='HOUR', values='CIG3000V3')
z_data = pivot_df.values

plotcolors = ['white', '#FFFFB2', '#FED976', '#FEB24C', '#FD8D3C', '#F03B20', '#BD0026']

fig, ax = plt.subplots(figsize=(6, 4))

x_axis = pivot_df.index.values  # 直接用透视表的行索引(1-12月)
y_axis = pivot_df.columns.values  # 直接用透视表的列索引(0,3,...21)

# 生成网格
x, y = np.meshgrid(x_axis, y_axis)

# 使用origin='lower'匹配SAS默认的Y轴递增方向,转置z_data适配网格维度
img = ax.contourf(x, y, z_data.T, origin='lower', 
                  levels=np.arange(0, 50, 5),  # 包含0值,覆盖数据中的低数值
                  colors=plotcolors,
                  extend='both')

# 网格设置
plt.grid(b=True, which='both', color='gray', linestyle='dashdot')
ax.set_yticks(y_axis)
ax.set_ylabel('Hour (UTC)')

# X轴月份缩写
positions = x_axis
labels = ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']
ax.xaxis.set_major_locator(ticker.FixedLocator(positions))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(labels))

# 颜色条
plt.colorbar(mappable=img, pad=.15, orientation='horizontal', extend='both', aspect=35)

plt.tight_layout()
plt.show()

关键说明

  • 透视表pivot确保了z_data的每一行对应一个月份,每一列对应一个小时,完全匹配坐标轴的维度,避免了reshape带来的顺序风险。
  • 使用origin='lower'让Y轴从下到上递增(0到21),和SAS的默认坐标方向一致;转置z_data是为了适配meshgrid的维度(meshgrid的y按行重复,z_data.T对应每个网格点的数值)。
  • 调整levels包含0值,覆盖原始数据中的低数值(比如6月、7月的3.2、2.1等),确保颜色映射完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:37:03