2. Python环境搭建与船舶设备数据初探
预测性维护的第一步不是建模,而是让数据“进得来、看得见”。本节我们完成三件事:搭好Anaconda与Jupyter的运行环境,用pandas读入一份船舶设备传感器数据集,并画出第一张设备运行趋势图。完成后,你将拥有一条可复用的最小数据链路:环境 → 数据文件 → DataFrame → 统计摘要 → 趋势图。
一、为什么选Anaconda + Jupyter
船舶设备数据往往来自振动加速度传感器、温度探头、压力变送器等不同采集通道,采样频率、量纲、缺失情况都不一致。Anaconda把Python解释器、pandas、NumPy、Matplotlib等科学计算库打包在一起,避免逐个安装时的版本冲突;Jupyter Notebook则以“代码块+输出”的形式逐段执行,非常适合边读数据边观察中间结果——这对初次接触设备数据的读者尤其友好。
安装时从Anaconda官网下载对应操作系统的安装包,安装向导中勾选“Add Anaconda to my PATH environment variable”可省去后续配置,若不勾选则通过开始菜单中的“Anaconda Prompt”启动命令行。安装完成后在命令行验证:
conda --version
python --version
jupyter notebook
最后一条命令会在浏览器中打开Jupyter主界面。建议为课程单独建一个环境,避免污染基础环境:
conda create -n ship-pm python=3.11 pandas matplotlib jupyter -y
conda activate ship-pm
环境名ship-pm只是示例命名,激活后命令行提示符前会出现该名称,说明当前使用的是独立环境。
二、准备一份船舶设备传感器数据集
本节使用一份教学示例数据集(非实测数据),模拟某船艉轴承与主海水泵在连续运行中的监测记录。文件名为ship_sensors.csv,采用长表结构:每行是一条“某设备某测点某时刻”的读数。字段设计如下:
| 字段 | 含义 | 示例值 |
|---|---|---|
| timestamp | 采集时间(分钟级) | 2024-05-01 08:00:00 |
| device_id | 设备编号 | BRG-01(艉轴承) |
| sensor | 测点类型 | vibration / temperature / pressure |
| value | 读数 | 2.31 |
| unit | 单位 | mm/s、℃、MPa |
长表的好处是新增设备或测点无需改表结构,缺点是同一时刻的多测点读数分散在多行,后续做趋势对比时需要按sensor筛选或透视。示例数据中,艉轴承振动在正常区间约1.5~2.5 mm/s,温度约45~55 ℃;主海水泵出口压力约0.35~0.45 MPa。这些数值仅用于演示,真实阈值应以设备说明书和船级社规范为准。
三、用pandas读取与基本统计
在Jupyter中新建笔记本,第一段代码完成导入与读取:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("ship_sensors.csv", parse_dates=["timestamp"])
print(df.shape)
print(df.head())
print(df.dtypes)
parse_dates让时间列直接成为datetime64类型,后续按时间排序、重采样都依赖它。若时间列格式特殊,可加dayfirst=True或自定义date_parser。读取后先看形状、前几行和类型,是排查“数字被读成字符串”“时间没解析”的最快手段。
接着做分组统计,这是理解数据分布的核心一步:
summary = df.groupby(["device_id", "sensor"])["value"].agg(
["count", "mean", "std", "min", "max"]
)
print(summary.round(3))
输出会给出每个设备每个测点的样本数、均值、标准差、最小值和最大值。重点看三处:一是count是否一致,若某测点明显偏少,说明存在缺失或采集中断;二是std是否异常大,可能混入了停机段或尖峰;三是max是否逼近报警阈值。还可以用df.isna().sum()统计缺失,用df["timestamp"].min()/max()确认时间覆盖范围。
value列被读成object类型,通常是文件中混入了单位符号或空字符串。可用pd.to_numeric(df["value"], errors="coerce")强制转换,转换后产生的NaN即为异常行,值得单独检查。四、绘制第一张设备运行趋势图
趋势图要回答的问题是:这台设备的某个测点,随时间如何变化,是否出现抬升或突变。以艉轴承振动为例:
brg = df[(df["device_id"] == "BRG-01") & (df["sensor"] == "vibration")]
brg = brg.sort_values("timestamp")
plt.figure(figsize=(10, 4))
plt.plot(brg["timestamp"], brg["value"], color="#1f77b4", linewidth=1.2)
plt.axhline(3.0, color="#d62728", linestyle="--", label="预警线 3.0 mm/s")
plt.title("BRG-01 艉轴承振动趋势(示例数据)")
plt.xlabel("时间")
plt.ylabel("振动速度 (mm/s)")
plt.legend()
plt.tight_layout()
plt.show()
图中横轴为时间、纵轴为振动速度,虚线是示例预警线。观察时关注三点:曲线是否整体缓慢上移(劣化趋势)、是否出现孤立尖峰(瞬时冲击或传感器干扰)、是否在某时段突然归零(停机或断线)。若时间轴标签重叠,可加plt.xticks(rotation=30);若数据点过密,可先按小时重采样取均值:brg.set_index("timestamp")["value"].resample("1h").mean()。
下面这张图把本节的数据链路与关键观察点串在一起,可作为操作时的对照参考:
五、结果如何判断
一张趋势图是否“读对了”,可以用几个具体动作验证。第一,把统计摘要中的max与图中最高点对照,若图中最高点远低于max,说明有离群点被坐标轴压缩或数据未排序。第二,检查count与时间跨度是否匹配:若按分钟采集、跨度为24小时,单测点应有约1440条记录,明显偏少就要查缺失。第三,把预警线与设备说明书中的振动烈度限值核对,示例中的3.0 mm/s只是演示值,实际应依据ISO 10816等标准或厂家规定。
完成本节后,你应当能独立复现这条链路:激活环境、读入CSV、打印形状与类型、按设备和测点分组统计、筛选单测点绘制带预警线的趋势图。这套流程虽然简单,却是后续特征提取、异常检测和剩余寿命预测的共同起点——数据读不对、统计看不准,后面的模型再复杂也没有意义。