pandas DataFrame按car_id分组后获取最低评分及对应国家代码的方法
问题解决方案
原有代码问题说明
你之前的实现返回结果异常,是因为x.loc[x.grade == x.grade.min(), 'country_code']返回的是Series类型对象而非标量值,输出时会自动带上索引、dtype等元信息,不符合预期。且apply+lambda的实现依赖逐组迭代,大数据量下性能较差。
最优pandas原生实现(无需apply)
推荐用「排序+分组取首行」的方案,代码简洁性能高:
result = ( df # 按车辆ID、评分升序排序,空评分默认排到分组末尾 .sort_values(['car_id', 'grade'], na_position='last') # 按车辆ID分组 .groupby('car_id', as_index=False) # 取每个分组第一条数据的对应字段,重命名为目标列名 .agg( min_grade=('grade', 'first'), min_grade_country=('country_code', 'first') ) )
运行输出结果如下:
| car_id | min_grade | min_grade_country |
|---|---|---|
| 123 | 1.0 | SK |
| 234 | 2.0 | SK |
| 345 | 1.0 | PL |
| 456 | NaN | CZ |
如果需要全为空评分的car_id对应的国家也返回空,可额外加一步处理:
result.loc[result['min_grade'].isna(), 'min_grade_country'] = pd.NA
并列最低分场景适配
如果存在同一个car_id对应多个国家评分相同且都是最低分的情况,需要保留所有对应国家的话,可以用关联的方式实现:
# 第一步:计算每个car_id的最低评分 min_grade_df = df.groupby('car_id', as_index=False)['grade'].min().rename(columns={'grade': 'min_grade'}) # 第二步:和原表关联,过滤出评分等于最低分的记录 result = df.merge(min_grade_df, on='car_id') result = result[result['grade'] == result['min_grade']][['car_id', 'min_grade', 'country_code']].rename(columns={'country_code': 'min_grade_country'})
内容的提问来源于stack exchange,提问作者Jaroslav Bezděk
相关产品推荐
相关产品推荐

