You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Pandas函数应用于DataFrame并合并结果为新DataFrame

问题:批量处理股票涨跌幅函数后无法合并DataFrame

我编写的get_returns_change_period函数可单独计算指定股票不同周期的涨跌幅(例如传入'XOM','EXXON MOBIL','High','Open'可正常运行),但通过lambda结合apply批量处理存储行业股票信息的df_Industry DataFrame时,无法将函数返回的多个股票DataFrame合并为一个统一的结果DataFrame。

原代码

涨跌幅计算函数

import pandas as pd
import yfinance as yF
import datetime
from functools import reduce

def get_returns_change_period(tic,com,OHLC_COL1,OHLC_COL2):
    df_Stock = yF.download(tickers = tic, period = "38y", interval = "1mo", prepost = False, repair = False)
    df_Stock['MONTH'] = pd.to_datetime(df_Stock.index)
    df_Stock = df_Stock.sort_values(by='MONTH')
    
    # 原计算逻辑存在重复错误,后续会修正
    df_Stock[com + ' % Change '+'3M'] = (((df_Stock[OHLC_COL1].shift(2) - df_Stock[OHLC_COL2]))/df_Stock[OHLC_COL2]) *100          
    df_Stock[com + ' % Change '+'3M'] = (df_Stock[com + ' % Change '+'3M'] * 100 )/df_Stock[OHLC_COL2]
    
    df_Stock[com + ' % Change '+'2M'] = (((df_Stock[OHLC_COL1].shift(1) - df_Stock[OHLC_COL2]))/df_Stock[OHLC_COL2]) *100          
    df_Stock[com + ' % Change '+'2M'] = (df_Stock[com + ' % Change '+'2M'] * 100 )/df_Stock[OHLC_COL2]
    
    df_Stock[com + ' % Change '+'M'] = (((df_Stock[OHLC_COL1].shift(0) - df_Stock[OHLC_COL2]))/df_Stock[OHLC_COL2]) *100          
    df_Stock[com + ' % Change '+'M'] = (df_Stock[com + ' % Change '+'M'] * 100 )/df_Stock[OHLC_COL2]
    
    return df_Stock.filter(regex='MONTH|% Change')

单独调用示例

get_returns_change_period('XOM','EXXON MOBIL','High','Open')

批量处理代码

df_Industry = pd.DataFrame({'ID':['1', '2'], 'Ticker': ['AIN', 'TILE'], 'Company':['Albany International', 'Interface']})

df1 = df_Industry.apply(lambda x: get_returns_change_period(x.Ticker, x.Company, 'High','Open'), axis=1)
df1

解决方案

步骤1:修正函数中的涨跌幅计算逻辑

原函数中重复执行了*100 / df_Stock[OHLC_COL2],导致计算结果严重偏离实际涨跌幅。正确的涨跌幅公式应为((后期值 - 初始值)/初始值)*100,修正后的函数如下:

def get_returns_change_period(tic, com, OHLC_COL1, OHLC_COL2):
    df_Stock = yF.download(tickers=tic, period="38y", interval="1mo", prepost=False, repair=False)
    df_Stock['MONTH'] = pd.to_datetime(df_Stock.index)
    df_Stock = df_Stock.sort_values(by='MONTH')
    
    # 修正后的涨跌幅计算逻辑
    # 注:shift(-2)表示取2个月后的OHLC_COL1值,若要对比过去2个月的数值,可改为shift(2)
    df_Stock[f'{com} % Change 3M'] = ((df_Stock[OHLC_COL1].shift(-2) - df_Stock[OHLC_COL2]) / df_Stock[OHLC_COL2]) * 100
    df_Stock[f'{com} % Change 2M'] = ((df_Stock[OHLC_COL1].shift(-1) - df_Stock[OHLC_COL2]) / df_Stock[OHLC_COL2]) * 100
    df_Stock[f'{com} % Change M'] = ((df_Stock[OHLC_COL1] - df_Stock[OHLC_COL2]) / df_Stock[OHLC_COL2]) * 100
    
    # 将MONTH设为索引,方便后续按月份对齐合并
    df_Stock = df_Stock.set_index('MONTH')
    return df_Stock.filter(regex='% Change')

步骤2:批量处理并合并DataFrame

使用列表推导式遍历df_Industry的每一行,获取单个股票的结果DataFrame,再通过pd.concat横向合并(自动按月份索引对齐,缺失月份填充为NaN):

df_Industry = pd.DataFrame({'ID':['1', '2'], 'Ticker': ['AIN', 'TILE'], 'Company':['Albany International', 'Interface']})

# 遍历每行获取单个股票的结果DataFrame
stock_dfs = [get_returns_change_period(row.Ticker, row.Company, 'High','Open') for _, row in df_Industry.iterrows()]

# 横向合并所有DataFrame,按月份索引自动对齐
result_df = pd.concat(stock_dfs, axis=1)

# 可选:将MONTH从索引恢复为普通列
result_df = result_df.reset_index()

替代方案:多股票场景下用reduce合并

如果处理的股票数量较多,可结合reduce和pd.merge按MONTH列进行outer合并,确保保留所有股票的所有月份数据:

from functools import reduce

# 调整函数,保留MONTH为普通列(不设为索引)
def get_returns_change_period(tic, com, OHLC_COL1, OHLC_COL2):
    df_Stock = yF.download(tickers=tic, period="38y", interval="1mo", prepost=False, repair=False)
    df_Stock['MONTH'] = pd.to_datetime(df_Stock.index)
    df_Stock = df_Stock.sort_values(by='MONTH')
    
    df_Stock[f'{com} % Change 3M'] = ((df_Stock[OHLC_COL1].shift(-2) - df_Stock[OHLC_COL2]) / df_Stock[OHLC_COL2]) * 100
    df_Stock[f'{com} % Change 2M'] = ((df_Stock[OHLC_COL1].shift(-1) - df_Stock[OHLC_COL2]) / df_Stock[OHLC_COL2]) * 100
    df_Stock[f'{com} % Change M'] = ((df_Stock[OHLC_COL1] - df_Stock[OHLC_COL2]) / df_Stock[OHLC_COL2]) * 100
    
    return df_Stock.filter(regex='MONTH|% Change')

stock_dfs = [get_returns_change_period(row.Ticker, row.Company, 'High','Open') for _, row in df_Industry.iterrows()]

# 按MONTH列outer合并所有DataFrame
result_df = reduce(lambda left, right: pd.merge(left, right, on='MONTH', how='outer'), stock_dfs)

内容的提问来源于stack exchange,提问作者prashanth manohar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:35:36