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

Pandas函数内条件判断问题求助:average_shares函数修正

Pandas函数修正求助:按id计算share_1和share_2平均值

我是Pandas新手,正在学习函数创建与if-else语句的实现。写了average_shares()函数但没达到预期效果,问题出在函数应该按行处理但我没搞对。非Pandas场景我会用for i in range(len(column))循环,但Pandas教程里常用apply(),而且函数参数是row不是DataFramedf,试了还是不行。

需求说明

现有包含id、week、order、share列的DataFrame,week会重复。需要为每个id计算share_1和share_2:

  • share_1:各周首次出现(index=1)的share平均值
  • share_2:各周第二次出现(index=2)的share平均值

规则

  1. 若某id的某周重复次数>2,先剔除share>0.95或<0.05的行再计算平均
  2. 若某周无重复(len<2),share_1等于该行share,share_2为0

当前代码

df = pd.DataFrame({'id': [1, 1, 1], 'week': [1, 1, 2], 'order': [2, 4, 3]})
df['index'] = df.groupby(['id', 'week']).cumcount()+1 #can be many id-s (not only id=1)
df['share'] = df['order']/df.groupby(['id', 'week'])['order'].transform('sum')
df['len'] = (df.groupby(['id', 'week']))['order'].transform('count')

def average_shares(df):
    if df['repeats']>2:
        df = df[(df['share'])>0.05 & (df['share']<0.95)]
        df['share_1'] = df[df['index']==1].groupby('id')['share'].transform('mean')
        df['share_2'] = df[df['index']==2].groupby('id')['share'].transform('mean')
    elif df['repeats']==2:
        df['share_1'] = df[df['index']==1].groupby('id')['share'].transform('mean')
        df['share_2'] = df[df['index']==2].groupby('id')['share'].transform('mean')
    elif df['repeats']<2:
        df['share_1'] = df['share']
        df['share_2'] = 0
    return df['share_1'], df['share_2']

df['share_1'], df['share_2'] = zip(*df.apply(average_shares, axis=1))

数据示例

inputcalculated需要计算的结果
idweekorder
-----------------
112
114
123

字段说明

  • len:同一week的重复次数
  • index:重复项的出现顺序
  • share:order除以该week的order总和
  • share_1:同一id下index=1的share平均值
  • share_2:同一id下index=2的share平均值

问题分析与修正方案

你的核心问题是误用了apply(axis=1)——当用axis=1时,函数接收的是单行数据(Series),而不是整个DataFrame,所以函数里不能直接对整个DataFrame做筛选、分组操作。另外代码里用了df['repeats'],但原DataFrame里只有len列,这也是一个错误。

正确思路是先按id和week处理数据,再按id聚合计算平均值,而非逐行处理。以下是修正后的代码:

import pandas as pd

df = pd.DataFrame({'id': [1, 1, 1], 'week': [1, 1, 2], 'order': [2, 4, 3]})
df['index'] = df.groupby(['id', 'week']).cumcount() + 1
df['share'] = df['order'] / df.groupby(['id', 'week'])['order'].transform('sum')
df['len'] = df.groupby(['id', 'week'])['order'].transform('count')

# 按(id, week)组过滤异常数据
def filter_group(group):
    if group['len'].iloc[0] > 2:
        return group[(group['share'] > 0.05) & (group['share'] < 0.95)]
    return group

filtered_df = df.groupby(['id', 'week']).apply(filter_group).reset_index(drop=True)

# 计算每个id下index=1和index=2的share平均值
id_index_mean = filtered_df[filtered_df['index'].isin([1,2])].groupby(['id', 'index'])['share'].mean().unstack()
id_index_mean.columns = ['share_1', 'share_2']
id_index_mean = id_index_mean.fillna({'share_2': 0})

# 合并结果到原DataFrame
result_df = df.merge(id_index_mean, on='id', how='left')

# 处理len<2的情况
mask = df['len'] < 2
result_df.loc[mask, 'share_1'] = result_df.loc[mask, 'share']
result_df.loc[mask, 'share_2'] = 0

print(result_df)

代码解释

  1. 组内过滤:按(id, week)分组,对重复次数>2的组过滤掉异常share值,保留有效数据。
  2. 聚合平均值:按id和index分组,计算每个id下index=1和index=2的share平均值,用unstack()将index转为列。
  3. 合并与规则处理:把平均值合并回原DataFrame,对len<2的行单独覆盖share_1和share_2的值。

运行后结果会符合你给出的数据示例要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:23:10