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

基于分组与条件在DataFrame中新增列的技术实现问询

高效实现DataFrame按ID分组生成didx和puidx列的方案

需求说明

初始数据

indexidtype
01d
12pu
23pu
33d
44pu
54d

赋值规则

若单个id仅对应1行:
   - 当type为'd'时:didx=-1,puidx=-10
   - 当type为'pu'时:didx=-10,puidx=-1
若单个id对应2行:
   - 当type为'd'时:didx=-1,puidx取同id另一行的index值
   - 当type为'pu'时:didx取同id另一行的index值,puidx=-1

预期输出

indexidtypedidxpuidx
01d-1-10
12pu-10-1
23pu3-1
33d-12
44pu5-1
54d-14

高效解决方案(向量化操作,推荐大数据量)

避免groupby.apply的逐组循环,采用pandas内置向量化操作实现O(n)时间复杂度的高效计算:

import pandas as pd

# 构造初始DataFrame(若已有数据可跳过此步)
df = pd.DataFrame({
    'index': [0, 1, 2, 3, 4, 5],
    'id': [1, 2, 3, 3, 4, 4],
    'type': ['d', 'pu', 'pu', 'd', 'pu', 'd']
}).set_index('index')

# 1. 计算每个id对应的行数
id_row_count = df.groupby('id')['type'].transform('count')

# 2. 获取同id另一行的index(针对2行的组,交换两行的index)
other_row_index = df.groupby('id')['index'].transform(
    lambda x: x.shift(-1) if len(x) == 2 else None
)
# 补全组内第二行的另一行index(shift(-1)会导致第二行NaN)
other_row_index = other_row_index.fillna(
    df.groupby('id')['index'].transform(lambda x: x.shift(1) if len(x) == 2 else None)
)

# 3. 初始化didx和puidx的默认值
df['didx'] = -1
df['puidx'] = -1

# 4. 处理单id单行的情况
single_row_mask = id_row_count == 1
df.loc[single_row_mask & (df['type'] == 'pu'), 'didx'] = -10
df.loc[single_row_mask & (df['type'] == 'd'), 'puidx'] = -10

# 5. 处理单id两行的情况
double_row_mask = id_row_count == 2
df.loc[double_row_mask & (df['type'] == 'pu'), 'didx'] = other_row_index
df.loc[double_row_mask & (df['type'] == 'd'), 'puidx'] = other_row_index

# 转换为整数类型(修正shift导致的浮点类型)
df[['didx', 'puidx']] = df[['didx', 'puidx']].astype(int)

# 输出结果
print(df.reset_index())

效率优势

  • 全程使用向量化操作,无Python层面的循环,比groupby.apply快数倍至数十倍(数据量越大优势越明显)
  • transform直接返回与原DataFrame同长度的结果,无需手动合并分组结果

备选方案:groupby+apply实现(适合小数据量)

如果数据量较小,可采用逐组处理的方式,代码逻辑更直观,但效率低于向量化方案:

import pandas as pd

# 构造初始DataFrame
df = pd.DataFrame({
    'index': [0, 1, 2, 3, 4, 5],
    'id': [1, 2, 3, 3, 4, 4],
    'type': ['d', 'pu', 'pu', 'd', 'pu', 'd']
})

def process_single_group(group):
    if len(group) == 1:
        # 处理单行id的情况
        if group['type'].iloc[0] == 'd':
            group['didx'] = -1
            group['puidx'] = -10
        else:
            group['didx'] = -10
            group['puidx'] = -1
    else:
        # 处理两行id的情况,获取对方行的index
        d_idx = group[group['type'] == 'd']['index'].iloc[0]
        pu_idx = group[group['type'] == 'pu']['index'].iloc[0]
        group.loc[group['type'] == 'd', 'puidx'] = pu_idx
        group.loc[group['type'] == 'pu', 'didx'] = d_idx
        # 填充默认值
        group['didx'] = group['didx'].fillna(-1)
        group['puidx'] = group['puidx'].fillna(-1)
    return group

# 分组处理并合并结果
df_result = df.groupby('id').apply(process_single_group).reset_index(drop=True)
print(df_result)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:30:46