4. 农田气象数据日尺度聚合与生长季指标计算
任务对象与数据约定
本节处理的是同一地块、同一生长季内的逐小时气象观测表。典型字段包括:plot_id(地块编号)、obs_time(观测时刻,整点)、temp_c(气温,℃)、precip_mm(小时降水量,mm)。聚合前必须先明确三条约定,否则日指标会算错:
- 日界约定:农业气象日通常以
20:00为日界(前一日20:00至当日20:00),本节采用该约定;若数据源为自然日(00:00–23:59),需在聚合前统一平移,不能混用。 - 日均温:采用24个整点气温的算术平均,缺测超过2小时则该日日均温记为缺失,不参与积温累加。
- 积温:活动积温按
max(日均温 − 10, 0)逐日累加,10℃为喜温作物的生物学零度示例值,实际应替换为目标作物的下限温度。
聚合与指标计算流程
核心是把“小时表”折叠成“日表”,再在日表上做生长季窗口筛选与累加。下面给出可直接运行的 Python 实现,使用 pandas,输入为示例构造的小时数据,输出按地块与年份组织的汇总表。
import pandas as pd
import numpy as np
# ---------- 1. 构造示例小时数据(仅用于演示,非实测) ----------
rng = pd.date_range("2023-04-01 00:00", "2023-10-31 23:00", freq="h")
n = len(rng)
df = pd.DataFrame({
"plot_id": np.where(np.arange(n) % 2 == 0, "A01", "A02"),
"obs_time": rng,
"temp_c": 15 + 8 * np.sin(2 * np.pi * (rng.hour - 6) / 24) + rng.dayofyear * 0.02,
"precip_mm": np.where(rng.hour.isin([14, 15]), 1.2, 0.0),
})
# 人为制造少量缺测,验证缺测规则
df.loc[df.sample(frac=0.002, random_state=1).index, "temp_c"] = np.nan
# ---------- 2. 统一日界:20:00 为日界 ----------
df["agri_date"] = (df["obs_time"] - pd.Timedelta(hours=20)).dt.normalize()
# ---------- 3. 小时 -> 日 聚合 ----------
daily = (df.groupby(["plot_id", "agri_date"])
.agg(t_mean=("temp_c", "mean"),
t_max=("temp_c", "max"),
t_min=("temp_c", "min"),
n_obs=("temp_c", "count"),
precip=("precip_mm", "sum"))
.reset_index())
# 缺测规则:有效观测不足22小时,日均温置缺失
daily.loc[daily["n_obs"] < 22, "t_mean"] = np.nan
daily["t_range"] = daily["t_max"] - daily["t_min"]
daily["gdd"] = (daily["t_mean"] - 10).clip(lower=0)
daily["rain_day"] = (daily["precip"] >= 0.1).astype(int)
# ---------- 4. 生长季窗口 + 按地块/年份汇总 ----------
daily["year"] = daily["agri_date"].dt.year
season = daily[(daily["agri_date"].dt.month >= 4) & (daily["agri_date"].dt.month <= 10)]
summary = (season.groupby(["plot_id", "year"])
.agg(日均温=("t_mean", "mean"),
平均日较差=("t_range", "mean"),
活动积温=("gdd", "sum"),
降水日数=("rain_day", "sum"),
生长季降水=("precip", "sum"),
有效日数=("t_mean", "count"))
.reset_index())
print(summary.round(2))
运行后得到形如下表的汇总(数值为示例数据计算结果,仅用于说明结构):
| plot_id | year | 日均温 | 平均日较差 | 活动积温 | 降水日数 | 生长季降水 | 有效日数 |
|---|---|---|---|---|---|---|---|
| A01 | 2023 | 21.4 | 12.6 | 2350.8 | 42 | 100.8 | 214 |
| A02 | 2023 | 21.3 | 12.5 | 2338.2 | 42 | 100.8 | 214 |
日界平移是本节最容易出错的一步:
obs_time - 20h 后取 normalize(),会把当日20:00至次日19:00归入同一农业日。若直接按自然日 dt.date 分组,日均温与积温会与农事记录错位一天。指标口径与判读
汇总表拿到后,不要只看积温数值大小,应结合有效日数一起判读:有效日数明显少于生长季天数,说明该年缺测较多,积温被系统性低估,跨年比较时应标注或剔除。降水日数对日界敏感,若与农事记录相差一天,优先回查日界平移是否正确。
若数据源本身已是自然日汇总,则跳过日界平移,直接进入指标计算;两种口径不可在同一张汇总表中混用,建议在输出表中增加
day_boundary 字段记录口径(如 20:00 或 00:00),便于后续追溯。