如何按列值的出现计数对pandas DataFrame进行排序
按指定列值的出现频次降序排列整个DataFrame
要实现同值行连续聚合、整体按值的出现计数从高到低排序、保留所有原有列的需求,有两种常用的高效实现方式:
方法1:映射计数值作为临时排序键(性能最优)
这种方法适合大数据量场景,没有额外的类型转换开销,执行速度最快:
- 第一步:直接通过
value_counts()获取目标列的频次统计,该方法默认返回结果就是按计数从高到低排序的结构,对应你示例中的顺序就是banana > peach > orange > apple:fruit_counts = df['fruit'].value_counts() - 第二步:给原表加一个临时排序列,把每一行的fruit值替换成它对应的总计数,按这个临时列降序排序后,再删掉临时列即可:
执行结果完全符合排序要求:最前2678行全部为fruit取值banana的记录,之后连续排列全部peach的对应行,接着是orange、apple的所有行,同值记录不会被打散。sorted_df = ( df # 给每个水果映射对应的总计数作为排序键 .assign(_temp_sort_col=df['fruit'].map(fruit_counts)) # 按计数从高到低排序 .sort_values('_temp_sort_col', ascending=False) # 删除临时排序列,完全保留原有列结构 .drop(columns='_temp_sort_col') # 重置索引,让排序后的行索引从0开始连续 .reset_index(drop=True) )
方法2:用有序分类变量指定排序优先级(灵活性更强)
如果后续需要手动调整类别的排序位置,或者需要保留原列的类型属性,可以用有序分类的方式实现:
- 首先提取按频次排序好的类别顺序列表:
ranked_categories = df['fruit'].value_counts().index.tolist() - 将目标列转换为带顺序的分类变量,再直接按列排序即可:
这种方法的优势是,只要修改sorted_df = ( df .assign( fruit=pd.Categorical( df['fruit'], categories=ranked_categories, ordered=True ) ) .sort_values('fruit') .reset_index(drop=True) )ranked_categories列表的元素顺序,就能直接调整不同类别的整体排序位置,不需要重新计算计数映射,适合需要反复调整排序规则的场景。
注意:两种方法的排序默认都是稳定排序,同类别内部的行顺序会保留原表中的相对顺序,如果需要同类别内随机打乱,可以在
sort_values里加kind='random'参数调整。
内容的提问来源于stack exchange,提问作者wannabedatasth
相关产品推荐
相关产品推荐

