基于条件移除分组低排名行的Pandas数据处理问题
问题描述
原始电影DataFrame如下:
Index Movie Rotten Tomato Score Director Ranking 1 Batman Rises 87 Christopher Nolan 1 2 Interstellar 73 Christopher Nolan 2 3 Legally Blonde 71 Robert Luketic 1 4 The Ugly Truth 14 Robert Luketic 2 5 (500) Days of Summer 85 Marc Webb 1 6 The Amazing Spider-Man 71 Marc Webb 2 7 Wide Awake 45 M N Shyamalan 1 8 The Last Airbender 5 M N Shyamalan 2
需求规则:
- 按导演分组后,若组内排名第1的电影烂番茄得分高于50(即>50%),仅保留该组内排名第1的电影
- 若组内排名第1的得分≤50,保留该组所有电影
理想结果:
Index Movie Rotten Tomato Score Director Ranking 1 Batman Rises 87 Christopher Nolan 1 3 Legally Blonde 71 Robert Luketic 1 5 (500) Days of Summer 85 Marc Webb 1 7 Wide Awake 45 M N Shyamalan 1 8 The Last Airbender 5 M N Shyamalan 2
尝试的错误代码:
movie_names = movie_names.groupby('Movie').filter(lambda g: (g.score <= 0.5).any())
这段代码错误移除了M N Shyamalan的所有电影,求正确实现方式。
解决方案
你的代码存在两个核心问题:
- 分组依据错误:应该按
Director分组,而非Movie - 得分判断逻辑错误:烂番茄得分是整数形式的百分比(比如87代表87%),你用了
0.5(对应0.5%),完全不符合实际规则;同时筛选逻辑也和需求不符。
这里提供两种简洁的实现方式:
方法1:使用groupby.filter
filtered_movies = movie_names.groupby('Director').filter( lambda g: # 情况1:组内第一名得分>50,仅保留排名1的行 ((g[g['Ranking'] == 1]['Rotten Tomato Score'].iloc[0] > 50) & (g['Ranking'] == 1)).any() # 情况2:组内第一名得分≤50,保留所有行 or (g[g['Ranking'] == 1]['Rotten Tomato Score'].iloc[0] <= 50) )
方法2:用transform广播组内第一名得分,再筛选
这种方法逻辑更清晰,便于调试:
# 计算每个导演组内排名第1的电影得分,广播到组内所有行 first_rank_score = movie_names.groupby('Director')['Rotten Tomato Score'].transform( lambda x: x[movie_names.loc[x.index, 'Ranking'] == 1].iloc[0] ) # 按需求筛选:要么第一名得分>50且当前行排名1,要么第一名得分≤50 filtered_movies = movie_names[ ((first_rank_score > 50) & (movie_names['Ranking'] == 1)) | (first_rank_score <= 50) ]
运行任意一种方法后,就能得到你想要的结果。
内容的提问来源于stack exchange,提问作者ds_1234
相关产品推荐
相关产品推荐

