用Python在GEE中自动化处理CHIRPS降水数据的完整指南
你是否曾经为了获取某个区域的月降水量数据,不得不手动下载几十张影像,然后在本地用Excel进行统计?这种重复性工作不仅耗时耗力,还容易出错。本文将带你用Google Earth Engine(GEE)的Python API,实现从数据获取到报表生成的全流程自动化。
1. 环境准备与基础配置
在开始之前,我们需要确保开发环境配置正确。与JavaScript版的GEE不同,Python环境提供了更强大的数据处理能力和更丰富的科学计算库支持。
首先安装必要的Python库:
pip install earthengine-api geemap pandas然后进行GEE的认证初始化:
import ee import geemap import pandas as pd # 初始化GEE ee.Authenticate() ee.Initialize()提示:如果你是第一次使用GEE Python API,需要先在Google Cloud平台创建项目并启用Earth Engine API服务。
接下来定义我们的研究区域。这里以中国长三角地区为例:
# 定义研究区域(长三角) roi = ee.Geometry.Polygon( [[[118, 30], [122, 30], [122, 32], [118, 32], [118, 30]]] )2. CHIRPS数据集的获取与预处理
CHIRPS(Climate Hazards Group InfraRed Precipitation with Station data)是目前全球范围内精度较高(0.05°)的降水数据集,结合了卫星观测和地面站点数据,特别适合区域气候研究。
加载CHIRPS日数据集的代码如下:
# 加载CHIRPS日数据集 chirps = ee.ImageCollection("UCSB-CHG/CHIRPS/DAILY").select('precipitation')为了后续分析方便,我们先定义一个计算月度统计量的函数:
def calculate_monthly_stats(collection, roi): # 按月份分组 monthly_collection = collection.map(lambda img: img.set('month', img.date().get('month'))) # 计算每月平均降水量 monthly_mean = monthly_collection.reduce(ee.Reducer.mean()).divide(30) # 转换为mm/day # 计算区域平均值 def region_mean(img): mean = img.reduceRegion( reducer=ee.Reducer.mean(), geometry=roi, scale=5000 ).get('precipitation_mean') return img.set('region_mean', mean) return monthly_mean.map(region_mean)3. 时间序列分析与统计报表生成
有了基础数据后,我们可以进行各种时间尺度的统计分析。首先来看如何生成月度降水报表:
def generate_monthly_report(start_year, end_year, roi): # 过滤时间范围 filtered = chirps.filter(ee.Filter.calendarRange(start_year, end_year, 'year')) # 计算月度统计 monthly_stats = calculate_monthly_stats(filtered, roi) # 提取数据到本地 stats_list = monthly_stats.aggregate_array('region_mean').getInfo() dates = monthly_stats.aggregate_array('system:time_start').getInfo() # 创建DataFrame df = pd.DataFrame({ 'date': pd.to_datetime(dates, unit='ms'), 'precipitation_mm': stats_list }) df['month'] = df['date'].dt.month df['year'] = df['date'].dt.year # 按月分组统计 monthly_report = df.groupby(['year', 'month']).agg({ 'precipitation_mm': 'sum' }).unstack() return monthly_report调用这个函数可以生成漂亮的月度报表:
monthly_report = generate_monthly_report(2010, 2020, roi) print(monthly_report)类似地,我们可以创建年度统计函数:
def generate_yearly_report(start_year, end_year, roi): # 过滤时间范围 filtered = chirps.filter(ee.Filter.calendarRange(start_year, end_year, 'year')) # 按年分组 yearly_collection = filtered.map(lambda img: img.set('year', img.date().get('year'))) # 计算年度总降水量 yearly_total = yearly_collection.reduce(ee.Reducer.sum()).divide(1000) # 转换为m # 计算区域平均值 def region_mean(img): mean = img.reduceRegion( reducer=ee.Reducer.mean(), geometry=roi, scale=5000 ).get('precipitation_sum') return img.set('region_mean', mean) yearly_stats = yearly_total.map(region_mean) # 提取数据到本地 stats_list = yearly_stats.aggregate_array('region_mean').getInfo() years = yearly_stats.aggregate_array('year').getInfo() # 创建DataFrame df = pd.DataFrame({ 'year': years, 'precipitation_m': stats_list }) return df.set_index('year')4. 高级分析与可视化技巧
基础报表生成后,我们可以进一步进行数据分析和可视化。首先安装必要的可视化库:
pip install matplotlib seaborn然后创建一个降水变化趋势分析函数:
import matplotlib.pyplot as plt import seaborn as sns def plot_precipitation_trend(report, title): plt.figure(figsize=(12, 6)) sns.lineplot(data=report.T, dashes=False, markers=True) plt.title(title) plt.ylabel('Precipitation (mm)') plt.xlabel('Month') plt.legend(title='Year', bbox_to_anchor=(1.05, 1), loc='upper left') plt.tight_layout() plt.show()调用这个函数可以生成漂亮的趋势图:
plot_precipitation_trend(monthly_report, 'Monthly Precipitation Trends (2010-2020)')对于年度数据,我们可以计算多年平均值和异常分析:
def analyze_annual_anomalies(yearly_report): # 计算长期平均值 long_term_mean = yearly_report.mean().values[0] # 计算异常值 yearly_report['anomaly'] = yearly_report['precipitation_m'] - long_term_mean yearly_report['percent_anomaly'] = yearly_report['anomaly'] / long_term_mean * 100 # 可视化 plt.figure(figsize=(10, 5)) bars = plt.bar(yearly_report.index, yearly_report['percent_anomaly'], color=['red' if x > 0 else 'blue' for x in yearly_report['percent_anomaly']]) plt.axhline(0, color='black', linewidth=0.8) plt.title('Annual Precipitation Anomalies (%)') plt.xlabel('Year') plt.ylabel('Deviation from Long-term Mean (%)') # 添加数值标签 for bar in bars: height = bar.get_height() plt.text(bar.get_x() + bar.get_width()/2., height, f'{height:.1f}%', ha='center', va='bottom') plt.tight_layout() plt.show() return yearly_report5. 报表导出与自动化工作流
最后,我们需要将生成的各种报表导出为常用格式,方便分享和进一步分析。
首先定义导出函数:
def export_reports(monthly_report, yearly_report, prefix='precipitation'): # 导出月度报表 monthly_report.to_excel(f'{prefix}_monthly.xlsx') # 导出年度报表 yearly_report.to_excel(f'{prefix}_yearly.xlsx') # 导出原始数据为CSV monthly_report.stack().reset_index().to_csv(f'{prefix}_monthly_raw.csv', index=False) yearly_report.reset_index().to_csv(f'{prefix}_yearly_raw.csv', index=False)为了实现完全自动化,我们可以将所有步骤封装到一个主函数中:
def generate_full_report(start_year, end_year, roi, prefix='precipitation'): print("Generating monthly report...") monthly = generate_monthly_report(start_year, end_year, roi) print("Generating yearly report...") yearly = generate_yearly_report(start_year, end_year, roi) print("Plotting trends...") plot_precipitation_trend(monthly, f'Monthly Precipitation Trends ({start_year}-{end_year})') yearly = analyze_annual_anomalies(yearly) print("Exporting reports...") export_reports(monthly, yearly, prefix) print("All done!") return monthly, yearly现在,只需一行代码就能完成从数据获取到报表导出的全过程:
monthly, yearly = generate_full_report(2010, 2020, roi, 'yangtze_delta_precip')注意:首次运行可能需要较长时间,因为GEE需要处理大量数据。后续运行会快很多,因为部分结果会被缓存。
在实际项目中,我发现将研究区域定义为可配置参数特别有用,这样同一套代码可以快速应用于不同地区。另外,异常检测功能对于识别极端气候年份非常有效,曾帮助我在一次研究中快速定位到2016年的强降水异常。