3. 数据读取与初步观察

拿到一份海洋数据文件,第一件事不是急着画图,而是把它“读进来、看清楚”。海洋数据常见的载体有三类:CSV 文本表、NetCDF 多维网格、Excel 工作簿。它们承载的信息结构差别很大——CSV 通常是“一行一个观测”的长表,NetCDF 是“维度 + 变量”的多维数组,Excel 则常被人工整理成带表头说明的混合布局。本节围绕“读入 → 看规模 → 认维度 → 做初判”这条主线,把三类格式的读取要点和初步观察方法讲清楚。

一、三类格式的读取入口

CSV 用 pandas.read_csv 最直接。海洋 CSV 常见的问题是表头不规范:有的首行是站点说明,有的用分号分隔,有的缺失值写成 -999 或 NaN 字符串。读取时应显式指定参数,而不是依赖默认推断:

import pandas as pd

df = pd.read_csv(
    "ctd_station.csv",
    sep=",",
    header=0,
    na_values=["-999", "-9999", "NaN", ""],
    parse_dates=["time"],
    encoding="utf-8"
)
print(df.shape)
print(df.dtypes)
print(df.head())

NetCDF 用 xarray 打开,它能自动解析维度、坐标和变量属性,是海洋网格数据的首选:

import xarray as xr

ds = xr.open_dataset("sst_monthly.nc")
print(ds)                 # 维度、坐标、变量一览
print(ds.dims)            # 各维度长度
print(ds.data_vars)       # 数据变量名
print(ds["sst"].attrs)    # 单位、缺测值、long_name

Excel 用 pandas.read_excel,关键是确认工作表名和数据起始行。人工整理的海洋观测表常在前几行放项目名、单位说明,真正表头在第 3 行左右,需要用 sheet_name 和 header 精确定位,必要时用 skiprows 跳过说明行。

二、看规模与结构:先建立“数据画像”

读入之后,先回答四个问题:有多少行多少列?每列是什么类型?有没有明显的缺测?时间与空间字段是否被正确解析?对 DataFrame,shape、dtypes、info()、describe() 能快速给出轮廓;对 NetCDF,ds.dims 告诉你维度长度,ds.coords 告诉你经纬度、时间、深度的取值范围,ds["变量"].attrs 里的 units、_FillValue、scale_factor 决定了数值是否需要换算。

一个容易被忽略的点是“维度顺序”。NetCDF 中温度变量可能是 (time, depth, lat, lon),也可能是 (time, lat, lon);如果误把深度当成时间切片,后续所有分析都会错位。因此读入后应打印 ds["temp"].dims,确认每个轴代表什么,再决定如何索引。

三、识别变量与维度:把“名字”对上“物理量”

海洋数据的变量名往往缩写严重,如 sst、sss、temp、salt、u、v、ssh。识别时不能只看名字,要结合 long_name、standard_name、units 三个属性交叉确认。例如 units="degrees_C" 说明是摄氏温度,units="1e-3" 配合 long_name="sea_water_salinity" 说明盐度以 10⁻³ 为单位,实际值需乘以 0.001。坐标变量同样要核对:经度是 0–360 还是 -180–180,纬度是南正还是北正,深度是向下为正还是向上为正。这些约定一旦弄反,剖面图和平面分布图都会出现镜像或倒置。

海洋数据读取与初步观察:三类格式 → 数据画像 → 变量维度核对 CSV 文本表 read_csv 一行一观测 · 长表 NetCDF 网格 xarray.open_dataset 维度+坐标+变量 Excel 工作簿 read_excel 表头/说明行需定位 数据画像四问 规模 shape · 类型 dtypes · 缺测 · 时间/空间解析 变量与维度核对(以 NetCDF 为例) 变量名 sst / temp / salt / u / v / ssh → 查 long_name、standard_name、units 维度顺序 (time, depth, lat, lon) → 确认每个轴含义,避免切片错位 坐标约定:经度 0–360 或 -180–180;深度向下为正;纬度南正/北正 初步统计描述与合理性判断 describe() 看范围与分位 · 缺测比例 · 单位换算(如盐度 ×0.001) 异常值初筛:-999 缺测、量级突变、经纬度越界

四、初步统计描述:用数字给数据“体检”

对表结构数据,df.describe() 会给出计数、均值、标准差、最小最大值和四分位数。海洋变量的合理范围可以作为第一道筛子:海表温度大致在 -2 ℃ 到 35 ℃ 之间,盐度约 0–40,流速分量通常在 ±3 m/s 以内。如果某列最大值出现 9999 或 -999,基本可以判定是缺测标记未被识别;如果盐度均值只有 0.035,则很可能是单位未换算。对 NetCDF,可用 ds["sst"].min()、.max()、.mean(skipna=True) 快速得到全局统计,并配合 ds["sst"].isnull().sum() 查看缺测分布。

统计描述不只是“看一眼”,而是要与物理常识对照。例如某月 SST 的 99% 分位数达到 45 ℃,就要怀疑是否混入了陆地格点或单位错误;某深度层盐度标准差接近零,可能是该层被整层填充了同一个缺测值。把这些初判记录下来,后续清洗才有依据。

五、一个可复用的观察清单

把上面的动作固化成一份简短清单,每次拿到新数据按序过一遍,能显著减少返工:

  • 读入参数:分隔符、表头行、缺测标记、编码、时间列是否显式指定。
  • 规模:行数、列数、维度长度,是否与预期站点数/格点数/时段吻合。
  • 类型:时间是否为 datetime,经纬度与深度是否为数值,分类字段是否被误读为数值。
  • 变量语义:long_name、units、_FillValue、scale_factor 是否核对。
  • 坐标约定:经度范围、纬度正负、深度方向,全文与图示保持一致。
  • 统计合理性:范围、分位数、缺测比例是否落在物理可信区间。
建议在 Notebook 中把“读入 + 画像 + 统计”写成一个小函数,返回 shape、dtypes、缺测比例和关键变量的 describe 结果。这样每换一个数据文件,只需改路径即可复现同一套检查,避免遗漏。

完成这一节的动作后,你应当能说清楚:这份数据有多少条记录、每个变量代表什么物理量、单位是什么、维度如何排列、缺测以什么形式存在、数值范围是否合理。只有这些“底账”清楚了,后面的清洗、插值、绘图和统计分析才建立在可靠的基础上。