使用apply将函数调用结果合并为DataFrame的问题
为什么Series.apply返回DataFrame组成的Series,而groupby.apply能合并成单个DataFrame?
核心差异:两种apply的行为逻辑不同
- Series.apply:本质是对序列中的每个元素独立执行函数,函数返回什么就把什么作为该位置的元素值。你的
get_opt_data返回单个DataFrame,所以最终得到的是一个每个元素都是DataFrame的Series,pandas不会自动帮你合并这些结果。 - groupby.apply:这是pandas为分组操作设计的特殊方法,它内置了结果合并逻辑:如果每个分组的函数返回的是DataFrame/Series,且这些结果的列结构兼容,pandas会自动将所有分组的结果**纵向拼接(pd.concat)**成一个完整的DataFrame。这是groupby独有的合并特性,普通的Series/DataFrame.apply没有这个逻辑。
解决方法:把Series中的DataFrame合并成单个DataFrame
方法1:用pd.concat直接合并
对apply返回的Series调用pd.concat,同时过滤掉可能的空值(避免某个ticker获取失败返回None导致报错):
ticker_list = pd.Series(['AAPL','GOOGL','MSFT','NVDA']) # 先获取所有DataFrame组成的Series,再合并 option_series = ticker_list.apply(lambda x: get_opt_data(x, '2023-07-21')) option_data = pd.concat(option_series.dropna())
方法2:用列表推导式(效率更高)
直接遍历ticker列表生成DataFrame,再合并,避免生成中间Series:
ticker_list = ['AAPL','GOOGL','MSFT','NVDA'] # 过滤掉返回None的结果 df_list = [get_opt_data(ticker, '2023-07-21') for ticker in ticker_list if get_opt_data(ticker, '2023-07-21') is not None] option_data = pd.concat(df_list)
优化你的get_opt_data函数
原函数存在两个可以优化的点:
- 重复调用
data.option_chain(expiration),浪费API请求; - 裸
except会隐藏所有错误,不利于排查问题。
优化后的代码:
import pandas as pd import yfinance as yf def get_opt_data(ticker, expiration): try: data = yf.Ticker(ticker) # 只调用一次期权链接口,减少请求次数 option_chain = data.option_chain(expiration) calls = option_chain.calls calls['Type'] = 'CALL' puts = option_chain.puts puts['Type'] = 'PUT' combined = pd.concat([calls, puts]) combined['Ticker'] = ticker info = data.info combined['Sector'] = info.get('sector', 'Unknown') # 用get避免key不存在报错 combined['Industry'] = info.get('industry', 'Unknown') return combined except Exception as e: # 打印错误信息,方便排查哪个ticker出问题 print(f"Failed to fetch data for {ticker}: {str(e)}") return None
内容的提问来源于stack exchange,提问作者Stix
相关产品推荐
相关产品推荐

