如何用Pandas Crosstab统计不同地形与距离下的第一名次数
问题:如何生成展示(地形,距离)组合下排名为1的次数的Pandas交叉表?
我有一个Pandas DataFrame,数据如下:
Terrain Distance Rank 77 Dirt 100 1 15 Grass 120 1 82 Road 180 1 4 Rock 100 1 107 Rock 120 1 70 Rock 200 1 115 Rock 200 1 37 Snow 160 1 57 Snow 160 1 95 Snow 160 1 193 Track 100 1 32 Dirt 100 2 97 Grass 140 2 51 Road 160 2 125 Road 180 2 90 Rock 140 2 60 Snow 120 2 78 Track 100 2 205 Track 120 2 33 Dirt 100 3 17 Dirt 140 3 53 Grass 100 3 161 Grass 100 3 43 Grass 160 3 81 Grass 160 3 103 Road 120 3 208 Road 160 3 58 Road 180 3 44 Rock 120 3 66 Rock 140 3 101 Rock 140 3 88 Rock 180 3 122 Rock 180 3 119 Sand 140 3 5 Sand 160 3 84 Snow 140 3 21 Snow 160 3 111 Snow 180 3 140 Track 140 3 29 Track 180 3 39 Track 200 3 2 Dirt 100 4 31 Dirt 140 4 102 Grass 140 4 134 Grass 160 4 108 Road 120 4 118 Road 120 4
我原本用以下代码生成统计所有记录数的交叉表:
# 频率表:使用crosstab()函数 my_crosstab = pd.crosstab(index=df["Terrain"], columns=df["Distance"], margins=True) # 包含行和列的总计 my_crosstab
生成的结果为:
Distance 100 120 140 160 180 200 All Terrain Dirt 12 5 9 5 4 5 40 Grass 4 5 8 8 2 6 33 Road 6 5 4 7 6 5 33 Rock 8 4 6 2 10 6 36 Sand 4 4 4 7 5 2 26 Snow 5 10 11 11 5 4 46 Track 9 6 4 6 6 4 35 All 48 39 46 46 38 32 249
现在需要修改代码,生成一个交叉表,每个单元格显示对应**(Terrain,Distance)组合下Rank=1的次数**,预期结果如下:
Distance 100 120 140 160 180 200 Terrain Dirt 1 Grass 1 Road 1 Rock 1 1 2 Sand Snow 3 Track 1
解决方案
方法1:直接使用crosstab的聚合参数
利用pd.crosstab的values和aggfunc参数,指定统计Rank列中等于1的次数:
# 统计各(Terrain, Distance)组合下Rank=1的次数 my_crosstab_rank1 = pd.crosstab( index=df["Terrain"], columns=df["Distance"], values=df["Rank"], aggfunc=lambda x: (x == 1).sum() ) # 可选:将0值替换为空,让表格更符合预期展示效果 my_crosstab_rank1 = my_crosstab_rank1.replace(0, "") my_crosstab_rank1
方法2:先筛选数据再生成交叉表
先过滤出Rank=1的行数据,再对这些数据生成交叉表,得到的就是对应组合的次数:
# 筛选出Rank=1的记录 df_rank1 = df[df["Rank"] == 1] # 生成交叉表 my_crosstab_rank1 = pd.crosstab( index=df_rank1["Terrain"], columns=df_rank1["Distance"] ) # 可选:补全所有地形和距离的组合,并将0替换为空 all_terrains = df["Terrain"].unique() all_distances = df["Distance"].unique() my_crosstab_rank1 = my_crosstab_rank1.reindex( index=all_terrains, columns=all_distances, fill_value=0 ).replace(0, "") my_crosstab_rank1
两种方法都能实现需求,方法2逻辑更直观,方法1则更为简洁。
内容的提问来源于stack exchange,提问作者Hugh Jackman
相关产品推荐
相关产品推荐

