使用Pandas GroupBy计算时新列出现NaN值的问题排查
解决分组计算盘整状态后新列全为NaN的问题
问题原因
使用groupby.apply()时,返回结果以分组键(stock_id)为索引,每个组的计算结果被打包为单个元素,无法与原DataFrame的全局索引对齐,导致赋值后新列所有值均为NaN。
解决方案
改用groupby.transform(),它会针对每个分组内的每一行生成对应结果,自动与原DataFrame的行完美对齐,彻底解决索引不匹配问题。
方式一:用lambda表达式简化实现
直接替换原代码中的赋值语句:
df['t'] = df.groupby("stock_id")['close'].transform( lambda x: np.where( (x.rolling(window=2, min_periods=2).min() / x.rolling(window=2, min_periods=2).max()) >= 0.95, True, False ) )
方式二:复用原函数并适配transform
先调整原函数,使其接收Series参数(更贴合transform的调用逻辑):
def is_consolidating(series, window=2, minp=2, percentage=0.95): rolling_min = series.rolling(window=window, min_periods=minp).min() rolling_max = series.rolling(window=window, min_periods=minp).max() return np.where((rolling_min / rolling_max) >= percentage, True, False)
再用transform调用函数:
df['t'] = df.groupby("stock_id")['close'].transform(is_consolidating)
额外优化点
原函数中pd.Series(df['close'])属于冗余操作,df['close']本身就是Series类型,可直接调用rolling方法。
完整修改后代码
import pandas as pd import sqlite3 as sql import numpy as np conn = sql.connect('allStockData.db') df = pd.read_sql_query("SELECT * from daily_ohlc_init", conn) def is_consolidating(series, window=2, minp=2, percentage=0.95): rolling_min = series.rolling(window=window, min_periods=minp).min() rolling_max = series.rolling(window=window, min_periods=minp).max() return np.where((rolling_min / rolling_max) >= percentage, True, False) df['t'] = df.groupby("stock_id")['close'].transform(is_consolidating) print(df) df.to_sql('daily_ohlc_init_with_indicators', if_exists='replace', con=conn, index=True)
内容的提问来源于stack exchange,提问作者a7dc
相关产品推荐
相关产品推荐

