3. 农业监测数据探索与质量概览
拿到一份农业监测数据,比如某试验田一个生长季的逐日气象与土壤记录,在动手清洗之前,第一步不是急着删行补值,而是先做一次“体检”。体检的目的很明确:搞清楚这份数据有多少行多少列、每列是什么类型、哪些字段缺失严重、有没有整行重复、数值范围是否落在合理区间。Pandas 提供了四个最常用的入口工具——info()、describe()、head()、tail(),配合缺失值、重复值和异常值的初步识别,能在几分钟内形成对数据质量的整体判断。
先看结构:info 与首尾抽样
info() 回答的是“数据长什么样”的结构问题。它会输出行数、列数、每列的非空计数、数据类型和大致内存占用。对农业监测数据来说,这一步特别关键:传感器导出的时间字段常常被读成字符串而不是 datetime64,土壤含水量可能因为个别空值被推断成 object,一旦类型不对,后续的排序、重采样、区间统计都会出错。因此看到 Dtype 列时,要逐列核对:时间列应为日期时间型,温度、湿度、降水、pH 应为数值型,地块编号、作物品种可以是类别型或字符串。
head() 和 tail() 则从两端抽样,帮助确认列名含义、单位约定和记录顺序。农业数据常带单位混用问题,比如温度列有的记录写“23.5”、有的写“23.5℃”,head() 一眼就能发现。同时看首尾还能判断时间是否连续、是否存在明显的排序错乱或尾部追加的异常批次。
import pandas as pd
df = pd.read_csv("field_monitor_2024.csv", parse_dates=["record_time"])
print(df.shape)
df.info()
print(df.head(5))
print(df.tail(5))
假设这份示例数据共 8760 行(一年逐小时记录)、9 列,info() 显示 soil_moisture 非空计数为 8420,说明约有 340 条缺失;air_temp 类型为 float64 正常,而 plot_id 被读成 int64,若它本应是带前导零的编号,就需要转成字符串。这些判断都来自 info() 的输出,而不是猜测。
再看分布:describe 与异常值初筛
describe() 默认对数值列给出计数、均值、标准差、最小值、四分位数和最大值。它是发现异常值最省力的手段。以 air_temp 为例,若输出最小值是 -85、最大值是 62,而该地区历史极值约为 -20 到 42,那么这两端就存在明显的录入或传感器故障嫌疑。同样,soil_moisture 的合理范围通常在 0~100(体积含水率百分比),若出现负值或 300 以上,基本可判定为异常。
只看极值还不够,四分位数能揭示偏态和离群程度。若 precipitation 的 75% 分位数是 0、最大值却是 180,说明降水高度稀疏且存在极端事件,这类分布不适合用均值填补缺失。对类别列,可以加 include="object" 参数查看频数、唯一值个数和众数,快速发现“玉米/玉米 /Corn”这类同物异名。
print(df.describe())
print(df.describe(include="object"))
# 缺失值概览
missing = df.isna().sum().sort_values(ascending=False)
print(missing[missing > 0])
print((df.isna().mean() * 100).round(2))
# 重复值
print("完全重复行:", df.duplicated().sum())
print("按时间+地块重复:", df.duplicated(subset=["record_time", "plot_id"]).sum())
缺失值识别要区分“完全缺失”和“业务性缺失”。前者是 NaN,后者可能是用 -999、0 或空字符串占位。农业传感器数据里 -999 作为缺测标记非常常见,如果直接 describe(),它会拉低均值、拉大标准差,必须先用 replace(-999, pd.NA) 统一成标准缺失再统计。重复值则要分两层看:完全重复行往往是导出时重复追加,直接 drop_duplicates() 即可;而按“时间+地块”重复,可能意味着同一时刻有多条不同来源的记录,需要判断保留哪一条,不能盲目删除。
把四类检查串成一次质量概览
下面的图示把本节的核心检查路径与判断依据组织在一起:从结构确认出发,分别走向缺失、重复、异常三条识别支路,每条支路都对应具体的 Pandas 手段和判读标准,最终汇入“是否进入清洗”的决策。
判读要点与常见陷阱
第一,describe() 只统计数值列,时间列和文本列不会出现,别因为没看到时间字段就以为它没问题,时间列要用 min()、max() 和 diff() 单独检查间隔是否均匀。第二,缺失率要结合业务看:某土壤传感器整月缺失,可能是设备离线,属于成段缺失,简单插值会制造虚假连续;而零星缺失才适合用前后值或均值填补。第三,异常值初筛阶段应以“标记”为主,把可疑记录筛出来存成单独视图,而不是直接删除,因为农业数据中的极端值有时恰恰是真实事件(如暴雨、霜冻),删掉会丢失关键信息。
把上述检查做完,你对这份数据的“底账”就清楚了:哪些列可信、哪些列需要重点处理、哪些记录需要回查原始日志。数据探索不是走形式,它决定了清洗策略的方向,也决定了后续统计分析结论是否站得住脚。