Pandas:groupby分组后apply自定义函数计算点击率结果异常求因
GroupBy自定义函数计算点击率结果异常的原因分析
问题描述
尝试通过GroupBy+自定义函数计算每个linkid的点击率,但结果不正确,代码如下:
def get_click_rate(data): click_count = data[data['event'] == 'click'].shape[0] view_count = data[data['event'] == 'pageview'].shape[0] return click_count / view_count data.groupby('linkid').apply(get_click_rate).reset_index(name='click rate')
而先过滤再分组合并的代码能得到正确结果:
click_event = data[data['event'] == 'click'].groupby('linkid')['event'].count().reset_index(name='click count') view_event = data[data['event'] == 'pageview'].groupby('linkid')['event'].count().reset_index(name='view count') merged_df = pd.merge(left=click_event, right=view_event, on='linkid', how='inner') merged_df['click rate'] = merged_df['click count'] / merged_df['view count']
疑惑:两者逻辑看似一致,仅执行顺序不同,为何结果不同?
核心差异点
结果集范围不同:
自定义函数的方法中,groupby('linkid')会包含所有存在的linkid,包括那些只有点击事件、只有浏览事件,甚至两种事件都没有的linkid。这些情况下计算出的点击率要么是inf(无浏览)、要么是0(无点击)、要么是NaN(无任何事件)。
而第二种方法用inner join合并,只会保留同时存在点击和浏览事件的linkid,自动过滤掉了上述特殊情况,所以最终结果集的范围更小,数据更符合预期。异常值处理缺失:
自定义函数没有处理view_count=0的场景,当某个linkid没有浏览事件时,除法运算会得到无穷大值inf,这显然不是合理的点击率,而第二种方法通过内连接直接排除了这类数据,避免了异常值。
修正建议
如果想用自定义函数的方法得到和第二种一致的结果,可以在函数里过滤掉无效情况,或者在结果后处理:
def get_click_rate(data): click_count = data[data['event'] == 'click'].shape[0] view_count = data[data['event'] == 'pageview'].shape[0] # 仅当浏览数大于0时返回点击率,否则返回None(后续可过滤) return click_count / view_count if view_count > 0 else None # 计算后过滤掉无效行 result = data.groupby('linkid').apply(get_click_rate).reset_index(name='click rate').dropna(subset=['click rate'])
内容的提问来源于stack exchange,提问作者Kareem Amr
相关产品推荐
相关产品推荐

