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

如何用向量化方法高效实现同DataFrame行对比并更新列?

问题

需要在同一DataFrame中,为参考symbol(XYZ)的行新增对应其他symbol的score列并填充匹配值。当前使用的迭代代码可实现需求,但处理2万行数据耗时数小时,寻求更高效的向量化实现方式。

原迭代代码及数据转换前后示例如下:

import pandas as pd
import numpy as np

df = pd.DataFrame({'date': ['2022-10-01', '2022-10-02', '2022-10-03', '2022-10-01', '2022-10-02'],
                   'symbol': ['XYZ', 'XYZ', 'XYZ', 'ABC', 'DEF'],
                   'tenor': ['2022-10-31', '2022-11-30', '2022-12-31', '2022-10-31', '2022-11-30'],
                   'score': [2, 3, 4, 6, 7],
                   })
ref_symbol = 'XYZ'
df_xyz = df.loc[df['symbol'] == ref_symbol]
sym_to_compare = list(df.symbol.unique())
sym_to_compare.remove(ref_symbol)
score_columns = [f'score_{sym}' for sym in sym_to_compare]
df[score_columns] = [np.NAN] * len(sym_to_compare)

for idx, row in df_xyz.iterrows():
    for sym in sym_to_compare:
        match = df.loc[(df.symbol == sym) & (df.tenor == row.tenor) & (df.date == row.date)]
        if len(match.index):
            df.at[idx, f'score_{sym}'] = match.score

数据转换前后示例

# 原始DataFrame
         date symbol       tenor  score
0  2022-10-01    XYZ  2022-10-31      2
1  2022-10-02    XYZ  2022-11-30      3
2  2022-10-03    XYZ  2022-12-31      4
3  2022-10-01    ABC  2022-10-31      6
4  2022-10-02    DEF  2022-11-30      7

# 转换后DataFrame
         date symbol       tenor  score  score_ABC  score_DEF
0  2022-10-01    XYZ  2022-10-31      2        6.0        NaN
1  2022-10-02    XYZ  2022-11-30      3        NaN        7.0
2  2022-10-03    XYZ  2022-12-31      4        NaN        NaN
3  2022-10-01    ABC  2022-10-31      6        NaN        NaN
4  2022-10-02    DEF  2022-11-30      7        NaN        NaN
高效向量化实现方案

利用pandas内置的pivot_table和merge操作实现完全向量化处理,避免逐行迭代,处理大体积数据时性能会有数量级的提升:

import pandas as pd
import numpy as np

df = pd.DataFrame({'date': ['2022-10-01', '2022-10-02', '2022-10-03', '2022-10-01', '2022-10-02'],
                   'symbol': ['XYZ', 'XYZ', 'XYZ', 'ABC', 'DEF'],
                   'tenor': ['2022-10-31', '2022-11-30', '2022-12-31', '2022-10-31', '2022-11-30'],
                   'score': [2, 3, 4, 6, 7],
                   })
ref_symbol = 'XYZ'

# 1. 按date和tenor聚合,将不同symbol的score转为列
pivot_df = df.pivot_table(
    index=['date', 'tenor'],
    columns='symbol',
    values='score',
    aggfunc='first'  # 确保每个(date,tenor,symbol)组合只取第一个值
)

# 2. 重命名列名,添加score_前缀,同时过滤掉参考symbol自身的列
pivot_df = pivot_df.rename(
    columns={sym: f'score_{sym}' for sym in pivot_df.columns if sym != ref_symbol}
)

# 3. 将聚合结果合并回原DataFrame
result_df = df.merge(pivot_df, on=['date', 'tenor'], how='left')

# 4. 非参考symbol的行,将新增的score_列设为NaN,与原需求结果对齐
non_ref_mask = result_df['symbol'] != ref_symbol
score_cols = [col for col in result_df.columns if col.startswith('score_')]
result_df.loc[non_ref_mask, score_cols] = np.nan

print(result_df)

方案优势

  • 所有操作均为pandas优化后的向量化运算,避免了嵌套循环的O(n²)时间复杂度,处理2万行数据仅需数秒
  • 代码逻辑清晰,易于维护和扩展
  • 自动处理所有symbol的匹配,无需手动遍历待对比symbol列表

内容的提问来源于stack exchange,提问作者B Jacob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:14:53