简介:这份资源面向气象、环境科学与气候研究方向的Python学习者,提供一套从数据读取到可视化呈现的完整实践素材,帮助解决气象观测数据处理与图表展示的实际问题。压缩包共15个文件,以10个CSV气象观测数据为主,配合4个Python脚本和1份说明文档,整体约14KB,体积轻便,便于快速上手运行与二次修改。内容围绕pandas、numpy、scipy等核心库展开,涵盖NetCDF、GRIB等气象格式的读取思路,以及缺失值处理、异常值检测、时间序列分析等预处理环节,并借助matplotlib、seaborn、plotly等工具绘制温度、湿度、风速随时间和空间变化的图形。脚本按data1至data4分模块组织,配套多个意大利城市的气象站数据,可对照代码理解数据导入、清洗、分析与出图的完整链路。目前已有9030人学习,适合希望系统掌握气象数据分析流程、积累可视化案例的读者参考。
1. 气象数据分析与可视化:从原始数据到可交付图表的完整链路
很多人拿到一份气象观测数据,第一反应是打开 Excel 画折线图,结果发现几万行数据卡到崩溃,时间轴挤成一团,风向数据根本没法用折线表示。气象数据分析与可视化这件事,核心难点从来不是画图本身,而是数据清洗、时间序列对齐、缺失值处理和图表类型选择这四件事。Python 在这个场景里的价值,是把从原始 CSV 到最终可交付图表的链路全部脚本化,换一批数据只需要改路径和列名。这篇文章面向的是手头有气象观测数据、需要用 Python 做分析和出图的从业者,不管你是气象站运维、农业环境监测还是能源行业的功率预测岗位,这套流程都能直接复用。下面从环境搭建讲到进阶技巧,每一步都有可复现的代码和参数说明。
2. 环境搭建与数据读取:把气象 CSV 正确加载进内存
2.1 依赖选型与安装命令
气象数据分析的依赖不多,但版本兼容性有讲究。核心四件套是 pandas、numpy、matplotlib、scipy。pandas 负责表格操作和时间序列重采样,numpy 处理数值计算和缺失值,matplotlib 出图,scipy 做插值和统计检验。如果要做交互式图表,再加 plotly 或 pyecharts。
安装命令如下:
pip install pandas numpy matplotlib scipy plotly如果你用的是 conda 环境,建议单独建一个环境,避免和系统 Python 冲突:
conda create -n weather python=3.10 conda activate weather pip install pandas numpy matplotlib scipy plotly参数说明:Python 版本建议 3.9 以上,pandas 2.x 对时间序列的支持更完善。matplotlib 中文字体需要额外配置,后面会讲。不要用 pip install 全局安装到系统 Python,气象数据处理经常需要固定版本复现结果。
2.2 读取气象 CSV 的三种典型格式
气象数据常见的存储格式有三种:标准 CSV(逗号分隔)、固定宽度文本(气象站老设备导出)、Excel 多 sheet。最常见的是 CSV,但编码和表头行数经常出问题。
import pandas as pd import numpy as np # 场景一:标准 CSV,第一行是列名 df = pd.read_csv( "weather_data.csv", encoding="utf-8", parse_dates=["datetime"], # 指定时间列自动解析 na_values=["", "NaN", "999999", "////"] # 气象数据常见缺失标记 ) # 场景二:表头不在第一行,前几行是站点信息 df = pd.read_csv( "station_data.csv", skiprows=5, # 跳过前5行元数据 encoding="gbk", # 国产气象设备常用GBK parse_dates=["观测时间"] ) # 场景三:固定宽度文本 df = pd.read_fwf( "old_station.txt", widths=[10, 8, 8, 8, 8], # 每列字符宽度 names=["站号", "日期", "气温", "气压", "风速"] )逻辑说明:parse_dates让 pandas 自动把时间列转成 datetime 类型,后续重采样和绘图都依赖这个类型。na_values是关键参数,气象数据里缺失值经常用 999999、////、空字符串混合表示,不统一处理后面全是坑。skiprows和encoding是国产气象设备导出的高频问题,GBK 编码不指定会直接报 UnicodeDecodeError。
参数说明:parse_dates可以传列名或列索引列表,多列时间字段用嵌套列表。na_values接受字符串或列表,建议把你能见到的所有缺失标记都列进去。read_fwf的widths必须和原始文件严格对齐,差一个字符整列错位。
2.3 数据初探与类型修正
读进来之后不要急着画图,先做三件事:看形状、看类型、看缺失。
# 基础信息 print(df.shape) # 行数和列数 print(df.dtypes) # 每列数据类型 print(df.isnull().sum()) # 每列缺失值数量 # 类型修正:气温、气压、风速应该是float df["气温"] = pd.to_numeric(df["气温"], errors="coerce") df["风速"] = pd.to_numeric(df["风速"], errors="coerce") # 时间列设为索引,方便重采样 df = df.set_index("datetime").sort_index() # 检查时间索引是否连续 full_range = pd.date_range(start=df.index.min(), end=df.index.max(), freq="h") missing_hours = full_range.difference(df.index) print(f"缺失时间点数量:{len(missing_hours)}")逻辑说明:pd.to_numeric配合errors="coerce"能把无法解析的值变成 NaN,比直接 astype 安全。set_index加sort_index是时间序列操作的前提,不排序后面重采样会报错。检查时间索引连续性是为了发现数据断档,气象数据经常有整段缺失,不检查的话画出来的图会骗你。
参数说明:freq="h"表示小时频率,如果数据是分钟级就改freq="min",日级改freq="D"。difference返回的是存在但数据里没有的时间点,数量超过总长度 5% 就要考虑插值还是直接截断。
3. 清洗与特征工程:缺失值、异常值和气象派生量
3.1 缺失值处理的四种策略与选择依据
气象数据的缺失值处理没有万能方案,取决于缺失比例和后续用途。我一般按这个决策链走:
| 缺失比例 | 推荐策略 | 适用场景 |
|---|---|---|
| < 5% | 线性插值 | 连续观测,短时断档 |
| 5% - 20% | 时间序列插值 + 标记 | 需要保留缺失标记供后续分析 |
| 20% - 50% | 同日同时刻均值填充 | 有明显日周期的要素 |
| > 50% | 删除该列或该时段 | 数据质量不可用 |
# 策略一:线性插值,适合短时断档 df["气温"] = df["气温"].interpolate(method="linear", limit=3) # 策略二:时间插值,考虑时间间隔 df["气温"] = df["气温"].interpolate(method="time") # 策略三:按同日同时刻均值填充 df["气温"] = df.groupby([df.index.hour, df.index.month])["气温"].transform( lambda x: x.fillna(x.mean()) ) # 策略四:标记缺失,不填充 df["气温_缺失"] = df["气温"].isnull().astype(int)逻辑说明:interpolate(method="linear")按索引顺序线性插值,limit=3限制最多连续插 3 个点,超过就保留 NaN,防止长段缺失被平滑掉。method="time"会考虑时间间隔不均匀的情况,比 linear 更准。按小时和月份分组填充利用了气象要素的日变化和季节规律,适合气温、湿度这类周期性强的变量。
参数说明:limit参数控制最大插值长度,气象数据建议不超过 6。transform保证返回的索引和原数据一致,不会因为分组打乱顺序。
3.2 异常值检测:3σ 还是 IQR
气象数据异常值检测常用两种方法:3σ 法和 IQR 法。3σ 假设数据正态分布,IQR 不假设分布。气温、气压近似正态,用 3σ;风速、降水偏态分布,用 IQR。
def detect_outliers_3sigma(series, threshold=3): """3σ法检测异常值,返回布尔索引""" mean = series.mean() std = series.std() return np.abs(series - mean) > threshold * std def detect_outliers_iqr(series, factor=1.5): """IQR法检测异常值""" q1 = series.quantile(0.25) q3 = series.quantile(0.75) iqr = q3 - q1 lower = q1 - factor * iqr upper = q3 + factor * iqr return (series < lower) | (series > upper) # 气温用3σ temp_outliers = detect_outliers_3sigma(df["气温"]) # 风速用IQR wind_outliers = detect_outliers_iqr(df["风速"]) # 异常值处理:标记而非直接删除 df["气温_异常"] = temp_outliers.astype(int) df.loc[temp_outliers, "气温"] = np.nan # 先置NaN再插值 df["气温"] = df["气温"].interpolate(method="time")逻辑说明:先标记再处理,保留异常标记列供后续追溯。直接删除异常值会丢失信息,置 NaN 再插值能保持时间序列连续。3σ 的 threshold 参数在气象数据里常用 3,但极端天气事件本身就是小概率,阈值设太小会把真实极端值当异常。
参数说明:factor=1.5是 IQR 的标准参数,气象数据可以放宽到 2.0 或 3.0,避免把大风天气误判为异常。异常值处理完要检查数据分布是否合理,气温突然从 35 度插值到 5 度肯定是哪里出了问题。
3.3 气象派生量计算:体感温度、露点、风矢量
原始气象数据往往只有气温、湿度、风速、风向,但分析时经常需要派生量。
# 露点温度(Magnus公式) def dew_point(temp, humidity): """temp: 摄氏度, humidity: 相对湿度(0-100)""" a, b = 17.27, 237.7 alpha = (a * temp) / (b + temp) + np.log(humidity / 100.0) return (b * alpha) / (a - alpha) df["露点"] = dew_point(df["气温"], df["相对湿度"]) # 体感温度(简化公式,考虑风速) def feels_like(temp, wind_speed): """temp: 摄氏度, wind_speed: m/s""" return 13.12 + 0.6215 * temp - 11.37 * wind_speed**0.16 + 0.3965 * temp * wind_speed**0.16 df["体感温度"] = feels_like(df["气温"], df["风速"]) # 风向转u/v分量(风向为角度,0度为正北) def wind_uv(wind_speed, wind_dir): """wind_dir: 气象风向角度,0=北,90=东""" rad = np.deg2rad(wind_dir) u = -wind_speed * np.sin(rad) # 东西分量 v = -wind_speed * np.cos(rad) # 南北分量 return u, v df["u"], df["v"] = wind_uv(df["风速"], df["风向"]) df["风向_弧度"] = np.deg2rad(df["风向"])逻辑说明:露点用 Magnus 公式,参数 a=17.27、b=237.7 是气象学标准值。体感温度公式里风速要转成 m/s,如果原始数据是 km/h 要先除以 3.6。风向转 u/v 分量是为了后续做风玫瑰图和矢量平均,直接对角度求平均是错的,0 度和 360 度平均出来是 180 度,完全反了。
参数说明:np.deg2rad把角度转弧度,numpy 三角函数只认弧度。u 分量前面的负号是因为气象风向定义是风的来向,u 分量指向东为正,所以来向为西时 u 为正,公式里加负号修正。
4. 可视化实战:时间序列、风玫瑰和热力图的代码实现
4.1 时间序列图:解决横坐标太密集的问题
气象数据动辄几千上万个时间点,直接 plot 横坐标会挤成一团黑。核心解决思路是控制刻度密度和旋转标签。
import matplotlib.pyplot as plt import matplotlib.dates as mdates # 中文字体配置(Windows) plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False # 负号正常显示 fig, ax = plt.subplots(figsize=(14, 5)) # 绘制气温曲线 ax.plot(df.index, df["气温"], linewidth=0.8, color="#e74c3c", label="气温") # 横坐标刻度控制:自动选择合适密度 ax.xaxis.set_major_locator(mdates.AutoDateLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter("%m-%d %H:%M")) plt.xticks(rotation=45, ha="right") # 或者手动指定:每6小时一个刻度 # ax.xaxis.set_major_locator(mdates.HourLocator(interval=6)) ax.set_xlabel("时间") ax.set_ylabel("气温 (℃)") ax.set_title("气温时间序列") ax.legend() ax.grid(alpha=0.3) plt.tight_layout() plt.savefig("temperature_timeseries.png", dpi=150) plt.show()逻辑说明:AutoDateLocator让 matplotlib 自动决定刻度密度,数据多的时候自动稀疏。DateFormatter控制显示格式,%m-%d %H:%M是月-日 时:分。rotation=45加ha="right"让标签右对齐旋转,避免重叠。tight_layout自动调整边距,防止标签被裁掉。
参数说明:figsize宽度建议 12 以上,气象时间序列横向信息多。dpi=150是屏幕查看和文档插入的平衡值,印刷用 300。如果数据点超过 10000,建议先重采样再画,否则渲染很慢。
4.2 风玫瑰图:用极坐标展示风向风速分布
风玫瑰图是气象可视化的标志性图表,用极坐标的扇形长度表示风向频率,颜色表示风速大小。
import numpy as np import matplotlib.pyplot as plt # 风向分箱:16个方位 dir_bins = np.arange(0, 361, 22.5) dir_labels = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"] # 风速分箱 speed_bins = [0, 2, 4, 6, 8, 10, 100] speed_labels = ["0-2", "2-4", "4-6", "6-8", "8-10", ">10"] colors = ["#2ecc71", "#3498db", "#f1c40f", "#e67e22", "#e74c3c", "#8e44ad"] # 统计每个风向每个风速段的频率 df["风向段"] = pd.cut(df["风向"], bins=dir_bins, labels=dir_labels, include_lowest=True) df["风速段"] = pd.cut(df["风速"], bins=speed_bins, labels=speed_labels) # 交叉表 ct = pd.crosstab(df["风向段"], df["风速段"]) ct = ct.reindex(dir_labels).fillna(0) # 保证16个方位都有 # 转成频率 ct_pct = ct.div(ct.sum(axis=1), axis=0) * 100 # 绘图 fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(111, projection="polar") ax.set_theta_zero_location("N") # 0度在正北 ax.set_theta_direction(-1) # 顺时针 angles = np.deg2rad(np.arange(0, 360, 22.5)) bottom = np.zeros(len(angles)) for i, label in enumerate(speed_labels): values = ct_pct[label].values ax.bar(angles, values, width=np.deg2rad(22.5), bottom=bottom, color=colors[i], label=label, edgecolor="white", linewidth=0.5) bottom += values ax.set_xticks(angles) ax.set_xticklabels(dir_labels) ax.legend(loc="upper right", bbox_to_anchor=(1.3, 1.0), title="风速 (m/s)") ax.set_title("风玫瑰图", pad=20) plt.tight_layout() plt.savefig("wind_rose.png", dpi=150) plt.show()逻辑说明:pd.cut把连续的风向和风速切成离散区间。crosstab生成交叉表,行是风向段,列是风速段。reindex保证 16 个方位顺序正确,缺的补 0。div(ct.sum(axis=1), axis=0)把计数转成每个风向内的频率百分比。极坐标里set_theta_zero_location("N")让 0 度朝北,set_theta_direction(-1)让角度顺时针增加,符合气象习惯。
参数说明:width=np.deg2rad(22.5)是每个扇形的角度宽度,16 方位正好 22.5 度。bottom累加实现堆叠效果。bbox_to_anchor把图例放到图外,避免遮挡。
4.3 热力图:用颜色矩阵展示多要素日变化
热力图适合展示「时间 × 要素」的二维模式,比如一天 24 小时、一年 12 个月的气温分布。
import seaborn as sns # 构造 月份 × 小时 的气温矩阵 pivot = df.pivot_table( values="气温", index=df.index.month, columns=df.index.hour, aggfunc="mean" ) fig, ax = plt.subplots(figsize=(14, 6)) sns.heatmap( pivot, cmap="RdYlBu_r", # 红黄蓝反转,红=高温 annot=False, # 不显示数值,太密 fmt=".1f", cbar_kws={"label": "气温 (℃)"}, ax=ax ) ax.set_xlabel("小时") ax.set_ylabel("月份") ax.set_title("气温月-小时热力图") plt.tight_layout() plt.savefig("temp_heatmap.png", dpi=150) plt.show()逻辑说明:pivot_table把数据按月份和小时聚合,aggfunc="mean"求平均。cmap="RdYlBu_r"是气象常用色带,红色高温蓝色低温,_r表示反转。annot=False因为 12×24 格子太密,标数值看不清。
参数说明:pivot_table的aggfunc可以换成max、min、std看不同统计量。cmap可选"coolwarm"、"viridis",但气象温度用红蓝色带最直观。如果数据有缺月,pivot_table会自动跳过,热力图会出现空白行。
5. 避坑与排查:气象可视化里最容易翻车的五个地方
5.1 中文字体显示成方块
现象:图表标题、轴标签里的中文全部变成方框,英文和数字正常。
原因:matplotlib 默认字体不含中文字形,Windows 下 SimHei 需要显式指定,Linux 和 macOS 字体名不同。
解决:先查系统可用字体,再设置 rcParams。
import matplotlib.font_manager as fm # 查看系统所有可用字体 fonts = [f.name for f in fm.fontManager.ttflist] print([f for f in fonts if "Hei" in f or "Song" in f or "YaHei" in f]) # Windows plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"] # macOS # plt.rcParams["font.sans-serif"] = ["Arial Unicode MS", "PingFang SC"] # Linux # plt.rcParams["font.sans-serif"] = ["WenQuanYi Micro Hei", "Noto Sans CJK SC"] plt.rcParams["axes.unicode_minus"] = False注意:axes.unicode_minus必须设 False,否则负号也会变方块。如果换了环境字体又失效,把字体文件路径直接传给 FontProperties 更稳。
5.2 时间轴排序错乱导致折线来回跳
现象:折线图出现大量来回穿插的竖线,时间轴顺序明显不对。
原因:数据读取后没有按时间排序,或者时间列被当成字符串排序("10:00" 排在 "9:00" 前面)。
解决:读入后立即转 datetime 并排序。
df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce") df = df.dropna(subset=["datetime"]).set_index("datetime").sort_index()排查方法:df.index.is_monotonic_increasing返回 False 就说明没排好。另外检查dtypes,时间列必须是datetime64[ns]而不是object。
5.3 风向平均算成 180 度反向
现象:计算平均风向时,结果和实际感受完全相反,或者风玫瑰图主风向和原始数据对不上。
原因:风向是角度,0 度和 360 度是同一个方向,直接对角度求算术平均会出错。比如 350 度和 10 度平均,算术平均是 180 度,实际应该是 0 度。
解决:转成 u/v 分量再平均,最后反算角度。
# 错误做法 # mean_dir = df["风向"].mean() # 不要这样 # 正确做法 u_mean = df["u"].mean() v_mean = df["v"].mean() mean_dir = (np.rad2deg(np.arctan2(-u_mean, -v_mean))) % 360参数说明:arctan2返回弧度,np.rad2deg转角度,% 360保证结果在 0-360。u/v 分量的正负号取决于坐标系定义,气象上 u 向东为正,v 向北为正。
5.4 重采样后数据量暴增或暴减
现象:resample之后行数不对,或者出现大量 NaN。
原因:resample的频率参数和数据实际频率不匹配,或者label、closed参数没设对。
解决:先确认原始数据频率,再设 resample 参数。
# 查看原始数据时间间隔 time_diff = df.index.to_series().diff().value_counts() print(time_diff.head()) # 看最常见的时间间隔 # 小时数据重采样为日数据 daily = df.resample("D").agg({ "气温": "mean", "降水": "sum", # 降水要累加 "风速": "max" }) # 关键参数:label控制标签在区间左还是右,closed控制区间开闭 daily = df.resample("D", label="left", closed="left").mean()注意:不同要素的聚合方式不同,气温用 mean,降水用 sum,风速用 max 或 mean。统一用 mean 会把降水量算错。
5.5 图片保存后空白或尺寸不对
现象:plt.savefig保存的图片是空白,或者尺寸和figsize不一致。
原因:savefig在show之后调用,或者bbox_inches参数没设导致标签被裁。
解决:先 save 再 show,加bbox_inches="tight"。
plt.tight_layout() plt.savefig("output.png", dpi=150, bbox_inches="tight", facecolor="white") plt.show() # show放最后参数说明:bbox_inches="tight"自动扩展边界包含所有标签。facecolor="white"防止透明背景在文档里显示成黑色。如果图片还是空白,检查是不是在plt.show()之后又创建了新 figure。
6. 进阶技巧:让气象图表从能看变成好用
6.1 双轴图:气温和气压叠加显示
气温和气压量纲不同,放同一个轴上气压会被压成直线。双轴图是标准解法。
fig, ax1 = plt.subplots(figsize=(14, 5)) # 左轴:气温 ax1.plot(df.index, df["气温"], color="#e74c3c", linewidth=0.8, label="气温") ax1.set_ylabel("气温 (℃)", color="#e74c3c") ax1.tick_params(axis="y", labelcolor="#e74c3c") # 右轴:气压 ax2 = ax1.twinx() ax2.plot(df.index, df["气压"], color="#3498db", linewidth=0.8, label="气压") ax2.set_ylabel("气压 (hPa)", color="#3498db") ax2.tick_params(axis="y", labelcolor="#3498db") # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left") ax1.set_xlabel("时间") ax1.xaxis.set_major_formatter(mdates.DateFormatter("%m-%d %H:%M")) plt.xticks(rotation=45, ha="right") plt.tight_layout() plt.savefig("temp_pressure.png", dpi=150, bbox_inches="tight") plt.show()逻辑说明:twinx()创建共享 x 轴的第二个 y 轴。两个轴的曲线颜色和轴标签颜色对应,读者一眼能分清。图例合并需要手动收集两个轴的 handles 和 labels。
参数说明:tick_params的labelcolor让轴刻度数字和曲线同色。如果两条曲线重叠严重,可以给其中一条加alpha=0.7透明度。
6.2 用 plotly 做可交互图表
静态图适合报告,交互图适合探索。plotly 的graph_objects可以做出带缩放、悬停提示的图表。
import plotly.graph_objects as go from plotly.subplots import make_subplots fig = make_subplots(specs=[[{"secondary_y": True}]]) fig.add_trace( go.Scatter(x=df.index, y=df["气温"], name="气温", line=dict(color="#e74c3c")), secondary_y=False ) fig.add_trace( go.Scatter(x=df.index, y=df["气压"], name="气压", line=dict(color="#3498db")), secondary_y=True ) fig.update_layout( title="气温与气压交互图", xaxis_title="时间", hovermode="x unified", # 悬停显示所有曲线值 template="plotly_white" ) fig.update_yaxes(title_text="气温 (℃)", secondary_y=False) fig.update_yaxes(title_text="气压 (hPa)", secondary_y=True) fig.write_html("interactive.html") fig.show()逻辑说明:make_subplots配合secondary_y=True实现双轴。hovermode="x unified"让鼠标悬停时显示该时间点所有曲线的值,比默认的逐点悬停好用。write_html导出独立 HTML 文件,可以直接发给别人用浏览器打开。
参数说明:template="plotly_white"是白色背景主题,适合文档插入。数据量超过 5000 点时建议先降采样,否则浏览器渲染卡顿。
6.3 批量出图:循环生成多站点图表
实际项目里往往有几十个站点,手动一个个画不现实。用循环加函数封装。
import os def plot_station(df, station_name, output_dir="output"): """为单个站点生成气温时间序列图""" os.makedirs(output_dir, exist_ok=True) fig, ax = plt.subplots(figsize=(12, 4)) ax.plot(df.index, df["气温"], linewidth=0.8, color="#e74c3c") ax.set_title(f"{station_name} 气温时间序列") ax.set_ylabel("气温 (℃)") ax.xaxis.set_major_formatter(mdates.DateFormatter("%m-%d")) plt.xticks(rotation=45, ha="right") plt.tight_layout() filepath = os.path.join(output_dir, f"{station_name}_temp.png") plt.savefig(filepath, dpi=150, bbox_inches="tight") plt.close(fig) # 关键:关闭figure释放内存 return filepath # 批量处理 stations = df["站号"].unique() for station in stations: station_df = df[df["站号"] == station].copy() plot_station(station_df, station) print(f"已生成:{station}")逻辑说明:plt.close(fig)是批量出图的关键,不关闭的话内存会持续增长,几十张图之后可能崩溃。os.makedirs(exist_ok=True)保证输出目录存在。函数返回文件路径方便后续记录。
参数说明:dpi=150批量出图时不要设太高,300 会让文件体积翻倍。如果站点数据量差异大,可以在函数里加判断,数据点少于 100 的跳过或单独处理。
6.4 一个我踩过的坑
早期做气象可视化的时候,我习惯把所有处理步骤写在一个脚本里,读数据、清洗、画图混在一起。结果换一批数据要改十几处路径和列名,改漏一处就报错。后来改成配置字典加函数分离,读数据、清洗、绘图各是一个函数,主流程只负责调用和传参。换数据只改配置字典里的路径和列名映射,其他代码不动。这个习惯帮我省了大量重复调试时间,也让脚本能直接交给同事复用。
另外,气象数据的时间列一定要在第一时间转成 datetime 并设为索引,不要等到画图的时候才转。我见过太多因为时间列是字符串导致排序错误、重采样失败的案例,提前处理好能避免后面 80% 的玄学问题。
希望帮到你。
本文还有配套的精品资源,点击获取