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

Python基于日值CSV计算多年月均值并按月份缩写绘图

Python处理加拿大环境部逐日气候观测数据实现方案

核心实现思路

  • 基于pandas做数据读取、清洗、聚合计算,对大规模逐日数据处理效率高,Spyder环境自带变量查看功能,入门阶段调试方便,后续批量处理15个站点只需封装函数循环调用即可,无需重复写代码。
  • 统计逻辑严格匹配需求拆分:
    • 先做数据清洗:剔除降水、气温关键字段为空的记录,过滤降水为负、气温超出合理区间的异常值,避免统计偏差
    • 第一层聚合(年+月维度):按年份、月份分组,对总降水量做当月逐日求和、对平均气温做当月逐日求均值,得到逐年逐月的基础统计表,作为后续多年统计、指定时段导出的数据源
    • 第二层聚合(月维度):基于逐年逐月表,按月份分组对月总降水量、月平均气温求跨年份均值,直接得到1-12月的多年月平均统计结果
  • 绘图采用matplotlib双Y轴方案,柱状图展示降水量、折线图展示气温,横轴替换为通用月份缩写,结果直观
  • 指定时段导出直接在逐年逐月基础表上做年份筛选,用pandas内置导出方法生成CSV即可。

首次运行前先在Spyder的IPython控制台执行命令安装依赖:
pip install pandas matplotlib numpy

完整参考代码

1. 基础导入与配置

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

# 配置绘图参数,兼容中文显示、负号正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

2. 数据读取与清洗

# 替换为本地存储的站点CSV文件路径
raw_df = pd.read_csv(
    '你的站点数据文件.csv',
    # 如果原始数据里用M/T等标记缺测,放开下面这行注释自动识别为空值
    # na_values=['M', 'T', '']
)

# 筛选计算需要的字段,剔除空值记录
use_cols = ['YYYY', 'MM', 'DD', 'Total Precip', 'Mean Temp']
raw_df = raw_df.dropna(subset=use_cols)

# 过滤异常值:降水量不能为负,气温合理区间设为-60℃到60℃,可根据站点实际情况调整
raw_df = raw_df[
    (raw_df['Total Precip'] >= 0) &
    (raw_df['Mean Temp'].between(-60, 60))
]

3. 生成逐年逐月基础统计数据

# 第一层聚合:按年、月分组,计算单月总降水量、单月平均气温
monthly_stats = raw_df.groupby(['YYYY', 'MM'], as_index=False).agg(
    month_total_precip = ('Total Precip', 'sum'),
    month_mean_temp = ('Mean Temp', 'mean')
)

4. 计算多年月平均值(对应需求1)

# 第二层聚合:按月份分组,计算所有年份同月的平均值
clim_stats = monthly_stats.groupby('MM', as_index=False).agg(
    avg_monthly_precip = ('month_total_precip', 'mean'),
    avg_monthly_temp = ('month_mean_temp', 'mean')
)

# 匹配月份缩写,用于后续绘图和导出
month_abbr_list = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
clim_stats['month_abbr'] = month_abbr_list

5. 绘制多年月均统计双轴图(对应需求2)

fig, ax_precip = plt.subplots(figsize=(10, 6))

# 左轴绘制降水量柱状图
ax_precip.bar(
    clim_stats['month_abbr'],
    clim_stats['avg_monthly_precip'],
    color='#2E86AB',
    alpha=0.7,
    label='多年月平均降水量'
)
ax_precip.set_xlabel('月份')
ax_precip.set_ylabel('平均降水量(mm)', color='#2E86AB')
ax_precip.tick_params(axis='y', labelcolor='#2E86AB')

# 右轴绘制气温折线图
ax_temp = ax_precip.twinx()
ax_temp.plot(
    clim_stats['month_abbr'],
    clim_stats['avg_monthly_temp'],
    color='#F24C00',
    marker='o',
    linewidth=2,
    label='多年月平均气温'
)
ax_temp.set_ylabel('平均气温(℃)', color='#F24C00')
ax_temp.tick_params(axis='y', labelcolor='#F24C00')

# 合并双轴图例
handles1, labels1 = ax_precip.get_legend_handles_labels()
handles2, labels2 = ax_temp.get_legend_handles_labels()
ax_precip.legend(handles1 + handles2, labels1 + labels2, loc='upper left')

plt.title('气候站多年月平均降水量与气温统计')
plt.tight_layout()
plt.show()

6. 导出指定时段逐月统计结果(对应需求3)

# 自定义需要导出的年份范围
target_start = 1980
target_end = 2010

# 筛选指定时段数据
export_df = monthly_stats[
    (monthly_stats['YYYY'] >= target_start) &
    (monthly_stats['YYYY'] <= target_end)
].copy()
# 增加月份缩写列方便查看
export_df['month_abbr'] = export_df['MM'].apply(lambda x: month_abbr_list[x-1])
# 调整列顺序
export_df = export_df[['YYYY', 'MM', 'month_abbr', 'month_total_precip', 'month_mean_temp']]
# 导出为CSV,用utf-8-sig编码避免Excel打开乱码
export_df.to_csv(
    f'站点{target_start}-{target_end}年逐月统计结果.csv',
    index=False,
    encoding='utf-8-sig'
)

批量处理15个站点的扩展方案

把单站点处理逻辑封装为函数,传入所有站点的文件路径循环调用即可,无需重复修改代码:

def process_single_station(csv_path, output_folder, export_start=1980, export_end=2010):
    """
    单气候站数据批量处理函数
    :param csv_path: 原始CSV文件路径
    :param output_folder: 结果存储文件夹路径
    :param export_start: 导出数据起始年份
    :param export_end: 导出数据结束年份
    """
    # 自动创建输出文件夹
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    # 读取清洗数据
    df = pd.read_csv(csv_path, na_values=['M', 'T', ''])
    df = df.dropna(subset=['YYYY', 'MM', 'DD', 'Total Precip', 'Mean Temp'])
    df = df[(df['Total Precip'] >= 0) & (df['Mean Temp'].between(-60, 60))]
    # 逐月聚合
    monthly = df.groupby(['YYYY', 'MM'], as_index=False).agg(
        month_total_precip=('Total Precip', 'sum'),
        month_mean_temp=('Mean Temp', 'mean')
    )
    # 导出指定时段结果
    station_name = os.path.basename(csv_path).split('.')[0]
    export_part = monthly[(monthly['YYYY'] >= export_start) & (monthly['YYYY'] <= export_end)]
    export_part.to_csv(
        f'{output_folder}/{station_name}_{export_start}-{export_end}逐月统计.csv',
        index=False,
        encoding='utf-8-sig'
    )
    return monthly

# 批量调用示例:把15个站点的CSV路径存入列表,循环执行即可
# station_file_list = ['站点1路径.csv', '站点2路径.csv', ..., '站点15路径.csv']
# for file in station_file_list:
#     process_single_station(file, './气候站统计结果/')

入门调试提示

  • Spyder右上角的变量浏览器可以直接点开所有DataFrame表格查看中间结果,不需要反复写print语句,方便核对计算是否正确
  • 如果读取CSV时报编码错误,给pd.read_csv()添加encoding='gbk'或者encoding='latin1'参数重试即可
  • 如果需要统计总降雨量、总降雪量、最高/最低气温的多年均值,直接在agg()函数里加对应字段的聚合规则就行,逻辑和现有统计完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:18:19