为何在Pandas数据处理中出现RuntimeWarning运行时警告?
Pandas计算出现RuntimeWarning问题排查
1. 数据结构与类型
使用的Pandas DataFrame包含priceNum、volumeNum、deliveryStart、execution、buySell列,其中deliveryStart和execution为UTC时间类型,buySell用于区分买卖方向。
数据类型详情:
priceNum float64 volumeNum float64 deliveryStart datetime64[ns, UTC] execution datetime64[ns, UTC] buySell object dtype: object
2. 分组计算逻辑
基于volumeNum列做计算,先按deliveryStart字段分组,将子DataFrame存入字典dfs_dict,执行代码如下:
dfs_dict={k: v for k, v in allOurTrades30min.groupby("deliveryStart")} for key in dfs_dict: sort_df(dfs_dict[key]) remaining=calc_remaining(dfs_dict[key]) if remaining<0: dfs_dict[key]["weightedOpening"]= (-calc_weighted(dfs_dict[key][dfs_dict[key]["buySell"]=="S"], remaining)) dfs_dict[key]["remaining"]= remaining else: dfs_dict[key]["weightedOpening"]= calc_weighted(dfs_dict[key][dfs_dict[key]["buySell"]=="B"], remaining) dfs_dict[key]["remaining"]= remaining
3. 问题现象
运行后触发警告:
/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:45: RuntimeWarning: invalid value encountered in double_scalars
排查后定位问题出在calc_remaining函数,函数代码如下:
def calc_remaining(df): remaining=0.0 for i in range(len(df)): if df.iloc[i]["buySell"] == "B": remaining = remaining + df.iloc[i]["volumeNum"] elif df.iloc[i]["buySell"] == "S": remaining = remaining - df.iloc[i]["volumeNum"] remaining = round(remaining,3) return remaining
部分子DataFrame计算结果正常,但有部分出现NaN异常值,合并后的最终结果也存在异常值。
问题分析与解决方案
可能的触发原因
- 空分组DataFrame:部分分组后的子DataFrame无数据,循环不执行,后续调用
calc_weighted时传入空数据引发计算异常 - 字段异常值:
buySell列存在非"B"/"S"的值(如NaN),或volumeNum列存在空值,导致加减操作后remaining变为NaN - 循环逻辑缺陷:逐行循环的方式无法高效处理空值与异常行,容易遗漏边界场景
优化后的calc_remaining函数
用Pandas向量化操作替代循环,同时加入异常值过滤:
def calc_remaining(df): # 过滤无效行:仅保留buySell为B/S、volumeNum非空的记录 valid_rows = df[(df["buySell"].isin(["B", "S"])) & (df["volumeNum"].notna())] if valid_rows.empty: return 0.0 # 向量化计算:B对应加volumeNum,S对应减volumeNum total = valid_rows.apply(lambda row: row["volumeNum"] if row["buySell"] == "B" else -row["volumeNum"], axis=1).sum() return round(total, 3)
增加防御性检查
在主循环中加入空数据检查,避免后续函数处理无效输入:
import pandas as pd for key in dfs_dict: df = dfs_dict[key] sort_df(df) # 处理空分组 if df.empty: df["weightedOpening"] = None df["remaining"] = 0.0 continue remaining = calc_remaining(df) # 处理remaining为NaN的情况 if pd.isna(remaining): df["weightedOpening"] = None df["remaining"] = 0.0 continue if remaining < 0: sell_subset = df[df["buySell"] == "S"] df["weightedOpening"] = -calc_weighted(sell_subset, remaining) if not sell_subset.empty else None else: buy_subset = df[df["buySell"] == "B"] df["weightedOpening"] = calc_weighted(buy_subset, remaining) if not buy_subset.empty else None df["remaining"] = remaining
优化说明
- 向量化操作比逐行循环更高效,同时能自动规避部分空值问题
- 提前过滤无效行,确保计算基于有效数据
- 增加多层空数据检查,避免因空输入触发计算异常
内容的提问来源于stack exchange,提问作者wolliumm
相关产品推荐
相关产品推荐

