3. 数据组织与文件格式
科研数据从采集到分析,往往要跨越多个软件环境:仪器导出 CSV,实验记录在 Excel,程序接口返回 JSON,仿真或观测结果则常存为 HDF5 或 NetCDF。文件格式不只是“后缀名”,它决定了数据的组织方式(行列表、键值树、多维数组)、类型精度、元数据能力和读写效率。选错格式,轻则丢失列类型或时间信息,重则无法表达多维网格,导致后续分析反复转换、口径混乱。本节围绕常用格式的结构特点与适用场景展开,并给出可执行的读取与转换练习。
一、五类常用格式的结构差异
CSV 是纯文本的二维表:每行一条记录,逗号分隔字段,首行常为列名。优点是通用、可版本管理、易被任何语言读取;缺点是所有值都是字符串,需要显式解析类型,且不支持多表、元数据和多维结构。适合规整的观测记录、问卷结果、中小规模表格数据。
Excel(.xlsx) 本质是压缩的 XML 包,一个工作簿可含多个工作表,支持公式、格式与单元格类型。它在实验记录和人工整理阶段非常方便,但公式结果依赖计算引擎、合并单元格会破坏“一行一记录”的整洁结构,且大文件读写慢。适合人工录入、少量多表数据;进入分析流程前通常应转为 CSV 或 DataFrame。
JSON 是键值对与数组嵌套的文本格式,能表达层级结构和不规则字段,是 Web API 与配置文件的通用载体。缺点是冗余度高、数值精度表示不统一、超大文件解析耗内存。适合接口返回、嵌套的实验元信息、参数配置。
HDF5 是二进制容器,内部像文件系统:组(group)构成层级,数据集(dataset)存放多维数组,属性(attribute)附带元数据,并支持分块、压缩和按切片读取。适合大规模多维数组、需要同时保存数据与描述信息的场景,如影像、光谱、机器学习特征集。
NetCDF 面向带坐标轴的科学网格数据,强调“维度—变量—属性”的自描述模型,广泛用于气象、海洋、遥感领域。经典 NetCDF 与 HDF5 在底层有渊源,现代 NetCDF4 常基于 HDF5 实现,因此二者都能表达多维数据,但 NetCDF 的坐标变量与单位约定更贴合地球科学工作流。
二、读取与转换的实操练习
下面以 Python 的 pandas、json、h5py、xarray 为例,完成一次“同一批实验数据在多种格式间流转”的练习。假设有一份传感器记录:采样时间、温度、湿度、设备编号,共 3 个采样点。示例数据为教学构造,非实测结果。
import pandas as pd, json, h5py, xarray as xr
# 1) 读取 CSV:显式指定时间列解析,避免被当成字符串
df = pd.read_csv("sensor.csv", parse_dates=["time"])
print(df.dtypes) # 检查 time 是否为 datetime64
print(df.shape) # 记录行列数,作为后续校验基准
# 2) 读取 Excel 的指定工作表,并丢弃全空行
df_x = pd.read_excel("sensor.xlsx", sheet_name="raw").dropna(how="all")
# 3) 读取 JSON:嵌套字段需先展开
with open("sensor.json", encoding="utf-8") as f:
obj = json.load(f)
df_j = pd.json_normalize(obj["records"]) # 将嵌套键转为扁平列
# 4) 写出 HDF5:按组存放,附带属性
with h5py.File("sensor.h5", "w") as h:
h.create_dataset("raw/data", data=df[["temp","hum"]].to_numpy())
h["raw/data"].attrs["units"] = "degC,percent"
h.attrs["source"] = "sensor.csv"
# 5) 写出 NetCDF:先构造带坐标的 Dataset
ds = xr.Dataset(
{"temp": (("time","point"), df.pivot(index="time", columns="point", values="temp").to_numpy())},
coords={"time": sorted(df["time"].unique()), "point": [1,2,3]},
attrs={"units": "degC"}
)
ds.to_netcdf("sensor.nc")
转换后必须做一致性校验,而不是“写完即结束”。常用检查包括:行数与列名是否一致、时间列是否仍为日期类型、数值列是否出现 NaN 增多、单位属性是否随数据一起写入。例如读取 HDF5 回验时,可用 h["raw/data"].shape 与原始 df.shape[0] 对比;读取 NetCDF 时用 ds["temp"].dims 确认维度顺序为 ("time","point"),避免转置错误。
把格式选择与校验固化为工作流的一部分,后续的清洗、统计与可视化才能建立在可信的数据底座上。建议在项目目录中同时保留 raw/(原始导出)、processed/(转换结果)与 scripts/(转换与校验脚本),使每一次格式转换都可追溯、可复现。