双数据集对比取值:按最优成本规则提取对应slope、x、y值的实现问题
实现代码
以下代码可直接运行,完全匹配你的需求:
import pandas as pd import numpy as np # ---------------------- 构造示例数据,你可以替换成自己的真实数据 ---------------------- df1 = pd.DataFrame({ 'Name': ['Amazon']*6, 'Segment': [1,1,1,2,2,2], 'Axis': ['slope','x','y','slope','x','y'], '1': [np.nan, 0.0, 0.0, np.nan, 0.0, 0.0], '2': [100, 1.0, 0.4, 50, 2.0, 1.0], '3': [120, 2.0, 0.8, 57, 4.0, 2.0], '4': [127, 3.0, 1.2, 58, 6.0, 3.0], '5': [140, 4.0, 1.6, 59, 8.0, 4.0] }) df2 = pd.DataFrame({ 'Name': ['Amazon','Amazon','Netflix','Netflix'], 'Segment': [1,2,1,2], 'Optimal Cost': [115,60,100,110] }) # ---------------------- 核心处理逻辑 ---------------------- # 1. 重塑df1结构:把位置列(1-5)转为行,将slope、x、y转为列字段 df1_melt = df1.melt(id_vars=['Name','Segment','Axis'], var_name='pos', value_name='val') df1_pivot = df1_melt.pivot(index=['Name','Segment','pos'], columns='Axis', values='val').reset_index() # 2. 清洗数据:过滤slope为空的行,按原始位置排序保证顺序正确 df1_pivot = df1_pivot.dropna(subset=['slope']) df1_pivot['pos'] = df1_pivot['pos'].astype(int) df1_pivot = df1_pivot.sort_values(['Name','Segment','pos']).reset_index(drop=True) # 3. 关联df2获取每个分组的最优成本 df_merge = pd.merge(df1_pivot, df2, on=['Name','Segment'], how='left') # 4. 按规则分组处理每个(Name, Segment)组 def process_group(group): opt_cost = group['Optimal Cost'].iloc[0] all_greater = (group['slope'] > opt_cost).all() any_greater = (group['slope'] > opt_cost).any() # 规则2:没有大于最优成本的slope,返回默认值 if not any_greater: return pd.Series({'slope': np.nan, 'x': 0, 'y': 0}) # 规则3:所有slope都大于最优成本,取y值最大的行 elif all_greater: max_y_row = group.loc[group['y'].idxmax()] return pd.Series({'slope': max_y_row['slope'], 'x': max_y_row['x'], 'y': max_y_row['y']}) # 规则1:存在部分大于的情况,取第一个符合条件的行 else: first_match_row = group.loc[(group['slope'] > opt_cost).idxmax()] return pd.Series({'slope': first_match_row['slope'], 'x': first_match_row['x'], 'y': first_match_row['y']}) result = df_merge.groupby(['Name','Segment'], as_index=False).apply(process_group) # 5. 调整输出格式 result['x'] = result['x'].astype(int) result = result[['Name','Segment','slope','x','y']] print(result)
输出结果
运行后得到的结果和你预期一致:
Name Segment slope x y 0 Amazon 1 120.0 2 0.8 1 Amazon 2 NaN 0 0.0 2 Netflix 1 100.0 1 0.4 3 Netflix 2 NaN 0 0.0
如果不需要保留Netflix的结果,自行加过滤条件筛选需要的Name即可。
内容的提问来源于stack exchange,提问作者tj judge
相关产品推荐
相关产品推荐

