1. 海洋监测数据获取与Python环境搭建

海洋监测的第一步不是画图,而是把“数据从哪里来、以什么格式存在、用什么工具读进来”这三件事理清楚。海洋观测数据来源分散、格式各异:浮标提供高频定点时间序列,卫星提供大范围遥感栅格,CTD提供垂向剖面,ADCP提供流速剖面。它们的时间分辨率、空间覆盖和文件结构差别很大,因此环境搭建的核心目标是建立一套能同时处理表格数据、NetCDF多维数组和地理空间绘图的稳定工具链。

一、常用数据源及其数据形态

理解数据源的关键是看它的“维度结构”,这直接决定后续用pandas还是xarray。

  • 浮标:通常以CSV或文本形式发布,每行一个观测时刻,字段包括时间、经纬度、风速、气温、水温、有效波高等。属于典型的一维时间序列,适合用pandas读取和重采样。
  • 卫星遥感:海表温度、叶绿素、海面高度等产品多为NetCDF或HDF格式,包含经度、纬度、时间三个维度,是规则网格数据,适合用xarray按维度切片。
  • CTD:温盐深剖面仪,一次投放得到一条随压力(深度)变化的剖面,字段为pressure、temperature、salinity。多站次数据可组织成“站次×深度”的二维结构。
  • ADCP:声学多普勒流速剖面仪,输出沿深度分层的东向、北向流速,维度通常是“时间×深度层”,用于分析流场垂向结构。

一个实用的判断原则是:数据若能用“行=样本、列=变量”描述,用pandas;若带有明确的命名维度(time、lat、lon、depth),用xarray。NetCDF文件本质是自描述的多维数组容器,xarray能直接读取其中的维度名、坐标和属性,比netCDF4的底层接口更适合分析。

二、环境配置

建议使用conda创建独立环境,避免地理绘图库的依赖冲突。cartopy依赖GEOS、PROJ等C库,用conda安装比pip省事得多:

conda create -n ocean python=3.11
conda activate ocean
conda install -c conda-forge xarray netCDF4 pandas matplotlib cartopy requests

安装完成后做一次最小验证,确认关键库能导入且cartopy能加载海岸线数据:

import xarray as xr, pandas as pd, requests
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature

ds = xr.tutorial.open_dataset("air_temperature")
print(ds.dims, ds.data_vars)

若cartopy首次绘图时报下载海岸线失败,通常是网络问题,可提前设置数据目录并手动放置shapefile,或改用cfeature.COASTLINE.with_scale("110m")降低数据量。

三、读取本地与远程数据

本地NetCDF用xarray一行打开,重点是先看结构再取数:

ds = xr.open_dataset("sst_202401.nc")
print(ds)                 # 查看维度、坐标、变量、属性
sst = ds["sst"].sel(time="2024-01-15", method="nearest")
sst.plot()                # 快速检查空间分布是否合理

远程数据分两种情况。若服务端支持OPeNDAP,xarray可直接按URL打开并只下载所需切片,避免整文件传输:

url = "https://example.org/thredds/dodsC/sst_202401.nc"
ds = xr.open_dataset(url)
sub = ds["sst"].sel(lat=slice(10, 25), lon=slice(110, 125)).isel(time=0)

若只是普通HTTP文件下载,用requests流式写入本地,避免大文件占满内存:

r = requests.get(url, stream=True, timeout=60)
r.raise_for_status()
with open("sst_202401.nc", "wb") as f:
    for chunk in r.iter_content(chunk_size=1 << 20):
        f.write(chunk)

浮标CSV则用pandas读取,并把时间列解析为索引,便于后续按小时或按天重采样:

df = pd.read_csv("buoy_41002.csv", parse_dates=["time"], index_col="time")
df = df[["wspd", "wvht", "wtmp"]].resample("1h").mean()

四、从原始文件到可分析对象的处理链

下图概括了本节的核心工作流:不同来源的数据经过对应的读取库,统一转换为pandas DataFrame或xarray Dataset,再进入matplotlib与cartopy完成可视化。图中同时标出了各环节最需要检查的质量点。

海洋监测数据读取与可视化处理链 数据源 浮标 CSV / 文本 时间序列 · 单点 卫星 NetCDF / HDF time × lat × lon CTD 剖面 站次 × 深度 ADCP 流速剖面 时间 × 深度层 读取方式 pandas.read_csv parse_dates 解析时间 xarray.open_dataset 本地路径或 OPeNDAP URL netCDF4 / xarray 按变量与维度切片 requests 流式下载 分块写入,控制内存 统一数据对象 DataFrame 行=样本 列=变量 时间索引 · 重采样 Dataset 命名维度 time/lat/lon 坐标对齐 · 切片 可视化输出 matplotlib 时间序列 / 剖面曲线 等值线 / 色标 cartopy 投影 · 海岸线 经纬度网格标注 读取后必须检查的质量点 ① 时间坐标是否被正确解析为 datetime,时区是否统一为 UTC;② 经纬度范围与分辨率是否符合预期,是否存在 0–360 与 −180–180 混用; ③ 缺测值是否已按 _FillValue 或 scale_factor 处理;④ 变量单位与量纲是否与绘图标签一致;⑤ 切片后维度顺序是否与绘图函数要求匹配。

五、一个可复现的最小示例

下面用一段代码把“读取—检查—绘图”串起来。示例使用xarray自带的教学数据集,参数与结果仅用于演示流程,不代表真实海区观测:

import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature

ds = xr.tutorial.open_dataset("air_temperature")
da = ds["air"].sel(time="2013-01-01", method="nearest")

fig = plt.figure(figsize=(8, 5))
ax = plt.axes(projection=ccrs.PlateCarree())
da.plot(ax=ax, transform=ccrs.PlateCarree(), cmap="RdYlBu_r")
ax.add_feature(cfeature.COASTLINE, linewidth=0.6)
ax.set_extent([-130, -60, 20, 55])
plt.title("示例:二维场空间分布")
plt.show()

判断结果是否合理,可以看三点:色标范围是否与变量物理量级相符;海岸线与数据网格是否对齐(不对齐通常是投影或经度范围设置错误);切片后的维度是否只剩lat和lon。若绘图报维度错误,先print(da.dims)确认,再用da.squeeze()去掉长度为1的多余维度。

建议在项目根目录固定一个data/目录存放原始文件,读取脚本中统一使用相对路径或配置变量,避免换机器后路径失效。远程数据优先尝试OPeNDAP按需切片,能显著减少下载量。

完成本节后,应能做到:识别四类海洋数据源的维度结构,选择pandas或xarray作为入口,用requests或open_dataset获取本地与远程文件,并在cartopy投影下画出第一张带海岸线的空间分布图。这套环境是后续所有分析与报表工作的基础。