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

如何在Pandas中按ID分组将brick值与同组其他项值做除法?

Pandas分组计算:生成同组brick值与其他item值的比值列

现有如下Pandas DataFrame:

id item val 
0 a  tire  5
1 a  brick 5
2 b  wheel 9
3 b  brick 6
4 c  ice   6
5 c  brick 3
6 d  brick 3
7 d  grass 6

需求说明

将每个同ID分组中brick的val值除以同组其他item的val值,生成新列per/brick,期望结果如下:

id item val per/brick
0 a  tire  5     1
1 a  brick 5     1
2 b  wheel 9     0.7
3 b  brick 6     1
4 c  ice   6     .5
5 c  brick 3     1
6 d  brick 3     .5
7 d  grass 6     2

错误尝试与问题分析

尝试通过for循环实现时出现错误:

perbrick=[]
for x in df['id']:
    if df[df['id']==x & df['item']!='brick']:
        perbrick.append(df[(df['id']==x)&(df['item']=='brick')]['val']/df[df['id']==x]['val']
    else:
        perbrick.append(1)

报错信息:TypeError: Cannot perform 'rand_' with a dtyped [object] array and scalar of type [bool]

错误原因

  1. 逻辑运算符优先级错误:&的优先级高于==和!=,代码中df['id']==x & df['item']!='brick'会被错误解析为df['id'] == (x & df['item']!='brick'),导致布尔值与字符串类型的ID进行位运算,触发类型不匹配错误。
  2. 循环取值逻辑混乱:直接通过df[df['id']==x]取分组数据,返回的是整个分组的DataFrame,赋值时会出现长度不匹配的问题,无法正确生成列表。

正确实现方法

推荐使用Pandas的分组操作(groupby+transform),避免低效循环,同时保证逻辑正确性:

方法一:分步实现

import pandas as pd

# 构造原始DataFrame
df = pd.DataFrame({
    'id': ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
    'item': ['tire', 'brick', 'wheel', 'brick', 'ice', 'brick', 'brick', 'grass'],
    'val': [5, 5, 9, 6, 6, 3, 3, 6]
})

# 按id分组,提取每组中item为brick的val值
brick_vals = df.groupby('id').apply(
    lambda group: group.loc[group['item'] == 'brick', 'val'].iloc[0]
)

# 将每组的brick值映射回原DataFrame,计算比值
df['per/brick'] = brick_vals[df['id']].values / df['val']

# 保留一位小数,与期望结果格式对齐
df['per/brick'] = df['per/brick'].round(1)

print(df)

方法二:简洁的transform写法

import pandas as pd

df = pd.DataFrame({
    'id': ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
    'item': ['tire', 'brick', 'wheel', 'brick', 'ice', 'brick', 'brick', 'grass'],
    'val': [5, 5, 9, 6, 6, 3, 3, 6]
})

# 用transform直接在分组内计算比值
df['per/brick'] = df.groupby('id').apply(
    lambda g: g['val'].apply(lambda x: g.loc[g['item'] == 'brick', 'val'].iloc[0] / x)
).explode().astype(float).round(1)

print(df)

结果说明

  • 两种方法都能正确生成per/brick列:brick自身的行比值为1(因为自身除以自身),其他item的行则是同组brick的val除以当前item的val。
  • 使用Pandas原生分组操作比循环效率更高,尤其在数据量较大时优势明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:35:56