如何按列的值计数对pandas数据框进行排序?

4

我希望对以下的pandas数据框按照 df['user_id'].value_counts() 的结果进行排序。

import pandas as pd
n = 100
df = pd.DataFrame(index=pd.Index(range(1, n+1), name='gridimage_id'))
df['user_id'] = 2
df['has_term'] = True
df.iloc[:10, 0] = 1

排序应该是稳定的,这意味着尽管用户2的行在用户1的行之前,但用户2的行和用户1的行仍将按原始顺序排列。
我考虑使用df.groupby,将df ['user_id'] .value_counts()与数据框合并,并将df ['user_id']转换为有序分类数据。然而,这些方法中没有一种特别优雅。
提前感谢您的任何帮助!
1个回答

12

transformargsort

对于稳定性,请使用kind='mergesort'

df.iloc[df.groupby('user_id').user_id.transform('size').argsort(kind='mergesort')]

factorize, bincount, 和 argsort

使用kind='mergesort'以保持稳定性。

i, r = pd.factorize(df['user_id'])
a = np.argsort(np.bincount(i)[i], kind='mergesort')
df.iloc[a]

回复评论

谢谢 @piRSquared。然而,能否反转排序顺序呢?value_counts默认是降序排列。在这个例子中,用户2有90行,而用户1只有10行。我想让用户2的行首先显示。不幸的是,Series.argsort忽略了order参数。 - Iain Dillingham 4分钟前

简单粗暴

将计数变为负数即可。

df.iloc[df.groupby('user_id').user_id.transform('size').mul(-1).argsort(kind='mergesort')]

或者

i, r = pd.factorize(df['user_id'])
a = np.argsort(-np.bincount(i)[i], kind='mergesort')
df.iloc[a]

谢谢@piRSquared。不过,是否有可能反转排序顺序呢?value_counts是按降序排列的。在这个例子中,用户2有90行,而用户1只有10行。我希望用户2的行首先出现。不幸的是,Series.argsort忽略了order关键字参数。 - Iain Dillingham
快速且简单的方法是将 np.bincount(i)[i] 的结果变为负数。 -np.bincount(i)[i]。我正在寻找更美观的解决方案。 - piRSquared

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接