pandas使用lambda结合assign/apply生成新列三类报错求解
问题根因
你的三种写法报错都是因为对pandas方法的传参逻辑理解有误:
- 第一种
assign写法:lambda里的x是整个init_df对象,x['DateIdentified']、x['Ticker']是整列Series对象,你把整列传给highestHigh做等值判断、日期比较时,pandas要求做比较的两个Series索引完全一致,否则就会抛出Can only compare identically-labeled Series objects错误。 - 第二种
Series.apply写法:你是对init_df.HighestHigh这个单列Series调用apply,传入lambda的x是该列的单个标量元素,你对标量用x['DateIdentified']这种键索引,自然会报string indices must be integers错误。 - 第三种写法:
axis参数是DataFrame.apply的专属参数,Series.apply没有这个参数,传参时直接抛出关键字参数不匹配的错误。
高效批量实现方案(无逐行Python循环)
不要用逐行apply或者iterrows的写法,这类写法本质是Python层循环,数据量稍大性能就会很差。可以用pandas原生的向量化操作实现,性能比循环写法高几十到上百倍:
核心思路是先预处理全量价格表,提前计算好每个股票每个日期到今日的区间最高价,再通过merge_asof一次性匹配到init_df的所有行,全程走numpy底层计算,没有逐行迭代。
import datetime import pandas as pd currDate = datetime.datetime.now().date() # 第一步:过滤掉价格表中晚于今日的无效数据 valid_price = allprice_df[allprice_df['date'] <= currDate].copy() # 第二步:按股票、日期升序排序,分组计算每个日期到今日的累计最高价 valid_price = valid_price.sort_values(['Ticker', 'date'], ascending=[True, True]) valid_price['max_high_to_today'] = valid_price.groupby('Ticker')['high'].transform( lambda x: x[::-1].cummax()[::-1] ) # 第三步:按股票代码做匹配合并,向前找第一个大于等于识别日期的价格记录,取提前算好的区间最大值 init_df = pd.merge_asof( init_df.sort_values('DateIdentified'), valid_price[['Ticker', 'date', 'max_high_to_today']].sort_values('date'), left_on='DateIdentified', right_on='date', by='Ticker', direction='forward' ) # 收尾:重命名列、清理冗余字段 init_df = init_df.rename(columns={'max_high_to_today': 'HighestHigh'}).drop(columns=['date'])
补充:apply的正确写法(不推荐,性能差)
你之前apply的调用对象写错了,应该对整个DataFrame调用apply传axis=1,而不是对单列Series调用:
# 仅作语法参考,数据量大于1万行时性能会明显下降 init_df['HighestHigh'] = init_df.apply( lambda row: highestHigh(row['DateIdentified'], row['Ticker'], allprice_df), axis=1 )
内容的提问来源于stack exchange,提问作者sud
相关产品推荐
相关产品推荐

