4. 用Pandas读取农业食品数据
在农业食品数据分析中,我们拿到的原始数据往往来自三个完全不同的渠道:农业农村部门发布的作物产量统计表、气象站导出的逐日观测记录、以及批发市场或电商平台导出的价格流水。这些数据可能是 CSV,也可能是 Excel,编码、列名、缺失值写法各不相同。Pandas 的 read_csv() 和 read_excel() 就是把这些"异构原料"统一成 DataFrame 的第一道工序。这一节我们围绕"读得进、读得对、看得清"三个目标展开:先掌握读取函数的关键参数,再处理列名、编码与缺失值标记,最后用结构查看方法确认数据是否按预期进入内存。
一、read_csv 与 read_excel 的核心参数
两个函数共享大量参数,理解它们的作用比死记参数表更重要。下面这张图把"文件 → 参数 → DataFrame → 结构检查"的读取链路和关键参数分组呈现出来,便于对照记忆。
实际读取时,最常见的写法是先把参数写全,再逐步精简。例如读取一份 GBK 编码、首行为列名、用"—"表示缺失的产量表:
import pandas as pd
yield_df = pd.read_csv(
"产量.csv",
encoding="gbk",
na_values=["—", "无", ""],
usecols=["年份", "地区", "作物", "播种面积", "总产量"]
)
print(yield_df.shape)
print(yield_df.head())
Excel 文件则多一个工作表选择问题。气象数据常把多个站点放在不同 sheet 中,此时 sheet_name 可以传名称、序号,甚至传 None 一次性读成"表名 → DataFrame"的字典,便于后续按站点循环处理。
二、列名、编码与缺失值:三个最容易踩的坑
列名问题分两类。一类是文件本身没有表头,数据从第一行就开始,这时要写 header=None,再用 names 显式给出列名;另一类是表头存在但含空格、换行或单位,如"总产量(吨)",读入后建议统一重命名为简洁的英文或拼音标识,避免后续用中文列名做运算时反复转义。重命名用 df.rename(columns={...}) 即可,注意 inplace 参数或重新赋值的选择要保持一致。
编码问题表现为中文变成乱码或直接抛 UnicodeDecodeError。判断方法很直接:Windows 下由 Excel 另存的 CSV 多为 GBK 系,Linux 或网页导出多为 UTF-8。遇到报错先换 encoding="gb18030",它兼容 GBK 且字符集更全;若仍失败,可用 chardet 探测,或先用文本编辑器另存为 UTF-8 再读。不要用 errors="ignore" 掩盖问题,那会静默丢字符。
缺失值标记是农业数据里最隐蔽的坑。气象表用"999"表示缺测,价格表用"-"表示当日无交易,产量表用空格表示未统计。Pandas 默认只把空字符串、NA、NaN 等识别为缺失,其余会当成正常字符串或数值读进来,导致均值、求和全部失真。正确做法是通过 na_values 补充业务标记;如果某些列本来就有合法取值与缺失标记冲突(例如产量列里 0 是真实值),则用字典形式按列指定:na_values={"单产": ["", "—"], "价格": ["-"]}。同时留意 keep_default_na,默认 True 会保留 Pandas 内置标记集,一般不必关闭。
df.isna().sum() 核对每列缺失数量,与原始表格的人工抽查结果对照。三、查看数据结构与基本信息
数据读进来不等于读对了。建议按固定顺序做四项检查:shape 确认行列数与预期一致;head() 与 tail() 抽查首尾,看列名是否错位、中文是否正常;info() 查看每列 dtype 和非空计数,若"年份"被读成 object 或"产量"被读成 object,说明混入了非数值字符;describe() 看数值列的均值、最值与分位数,异常的最大值往往就是漏标的缺测码。
| 检查方法 | 关注点 | 典型异常信号 |
|---|---|---|
df.shape | 行数、列数 | 行数远少于源文件,可能被错误分隔符截断 |
df.head() | 列名、首行内容 | 列名变成"Unnamed: 0",说明索引列被误读 |
df.info() | dtype、非空计数 | 数值列显示 object,存在非数值字符 |
df.describe() | 最值、分位数 | 最大值 999 或 -999,疑似缺测码未处理 |
以价格数据为例,若 info() 显示"价格"列为 object,可进一步用 pd.to_numeric(df["价格"], errors="coerce") 转换,转换后新增的 NaN 就是无法解析的脏值,再回查原始行定位问题。这一步与读取阶段的 na_values 形成互补:前者处理"已知标记",后者兜底"未知脏值"。
把三类数据都读成干净的 DataFrame 之后,后续的合并、清洗与统计才有可靠基础。本节的关键不在于记住所有参数,而在于形成"先判断文件特征、再配置参数、最后用结构检查验证"的稳定习惯——读得进只是起点,读得对才是目的。