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

如何在两个DataFrame间按Range列映射值并执行除法运算

高效实现DataFrame元素按区间匹配的除法运算

问题概述

现有两个Pandas DataFrame:df和df2,二者列名基本一致(df2多一列Range存储数值区间)。需要对df中的每个元素,根据其值所在的df2区间,找到df2对应列的元素,执行df元素 / df2对应元素的运算,要求高效实现,避免逐元素循环。

原始数据定义

import pandas as pd

# 定义df
d = {'Col1': [10,67], 'Col2': [30,10],'Col3': [70,40]}
df = pd.DataFrame(data=d)

# 定义df2
df2 = pd.DataFrame(
    data=[[25,36,47,(0,20)], [70,85,95,(20,40)], [12,35,49,(40,60)], [50,49,21,(60,80)], [60,75,38,(80,100)]],
    columns=["Col1","Col2","Col3","Range"]
)

解决方案一:按列批量处理(简洁高效)

这种方法通过pd.cut快速匹配区间索引,直接对整列进行运算,仅需遍历列(列数通常远少于行数),效率很高。

result_df = df.copy()
# 提取区间的上下限,生成用于cut的bins
bins = [interval[0] for interval in df2['Range']] + [df2['Range'].iloc[-1][1]]

for col in df.columns:
    # 为df当前列的每个值匹配对应的区间索引
    interval_indices = pd.cut(
        df[col],
        bins=bins,
        labels=False,
        include_lowest=True  # 确保最小值落在第一个区间内
    )
    # 提取df2对应列的匹配值,执行除法运算
    result_df[col] = df[col] / df2[col].iloc[interval_indices].values

运行后result_df的输出:

Col1      Col2      Col3
0  0.400  0.352941  3.333333
1  1.340  0.277778  0.816327

解决方案二:长格式合并(适合超大数据集)

如果数据集行数极多,可通过merge_asof实现基于排序的高效合并,时间复杂度为O(n log n),避免列循环。

  1. 预处理df2,拆分区间为上下限:
df2[['lower', 'upper']] = pd.DataFrame(df2['Range'].tolist(), index=df2.index)
  1. 将df转为长格式,方便按值和列名匹配:
df_melt = df.reset_index().melt(id_vars='index', var_name='column', value_name='df_value')
  1. 对df2和df_melt排序,满足merge_asof的要求:
df2_sorted = df2.sort_values('lower')
df_melt_sorted = df_melt.sort_values('df_value')
  1. 按列分组匹配区间,计算除法后转回原格式:
# 将df2的列也转为长格式,方便匹配
df2_melt = df2_sorted.melt(
    id_vars=['lower', 'upper'],
    var_name='column',
    value_name='df2_value'
)

# 用merge_asof按列匹配区间
merged = pd.merge_asof(
    df_melt_sorted,
    df2_melt,
    by='column',
    left_on='df_value',
    right_on='lower',
    direction='backward'
)

# 过滤出值在区间内的行(确保df_value < upper)
merged = merged[merged['df_value'] < merged['upper']]

# 计算除法并转回原DataFrame结构
merged['result'] = merged['df_value'] / merged['df2_value']
result_df = merged.pivot(index='index', columns='column', values='result').rename_axis(None, axis=1)

关键说明

  • 两种方法均避免了逐元素循环,适合大规模数据处理;
  • 区间匹配默认采用左闭右开规则(如(0,20)包含0但不包含20),若需调整可修改pd.cut的right参数或merge_asof的过滤条件;
  • merge_asof方法更适合列数多、行数极大的场景,按列处理的方法则更简洁易读。

内容的提问来源于stack exchange,提问作者Martin Yordanov Georgiev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 06:24:35