手动计算多列的排名平均值
Compute rank average for multiple columns manually
我正在寻找一种基于多列生成排名的方法,其中一列包含字符串,另一列包含整数(可能很容易超过 2 列,但为了更容易,我限制为 2 列例如)。
import pandas as pd
df = pd.DataFrame(data={'String':['a','a','a','a','b','b','c','c','c','c'],'Integer':[1,2,3,3,1,3,6,4,4,4]})
print(df)
String Integer
0 a 1
1 a 2
2 a 3
3 a 3
4 b 1
5 b 3
6 c 6
7 c 4
8 c 4
9 c 4
我们的想法是能够创建排名,按字符串降序排列每行,整数按升序排列,这将是输出:
Rank String Integer
0 2 c 4
1 2 c 4
2 2 c 4
3 4 c 6
4 5 b 1
5 6 b 3
6 7 a 1
7 8 a 2
8 9.5 a 3
9 9.5 a 3
到目前为止,这是我设法做到的,但我在共享排名时如何生成 'average' 时遇到了问题。
df['concat_values'] = df['String'] + df['Integer'].astype(str)
df = df.sort_values(['String','Integer'],ascending=[False,True])
df = df.reset_index(drop=True).reset_index()
df['repeated'] = df.groupby('concat_values')['concat_values'].transform('count')
df['pre_rank'] = df['index'] + 1
df = df.sort_values('pre_rank')
df = df.drop('index',axis=1)
print(df)
String Integer concat_values repeated pre_rank
0 c 4 c4 3 1
1 c 4 c4 3 2
2 c 4 c4 3 3
3 c 6 c6 1 4
4 b 1 b1 1 5
5 b 3 b3 1 6
6 a 1 a1 1 7
7 a 2 a2 1 8
8 a 3 a3 2 9
9 a 3 a3 2 10
我想过使用一些过滤或公式,以便当 repeated
列的值大于 1 时,pre_rank
得到应用的函数 returns 平均值,但是该函数不能推广到所有行,它适用于第一行,但它会为第二行产生更高的值(因为 pre_rank
现在具有更高的值)。我相信我只是错过了完成它的最后一步,但无法解决。谢谢!
我的方法:
df = df.sort_values(['String','Integer'], ascending=[False, True])
df['rank'] = np.arange(len(df)) + 1
df['rank'] = df.groupby(['String', 'Integer'])['rank'].transform('mean')
输出:
String Integer rank
7 c 4 2.0
8 c 4 2.0
9 c 4 2.0
6 c 6 4.0
4 b 1 5.0
5 b 3 6.0
0 a 1 7.0
1 a 2 8.0
2 a 3 9.5
3 a 3 9.5
sort
+ ngroup
+ rank
.
需要您在 groupby 中指定 sort=False
,以便 ngroup
标签按照您排序的顺序生成。
df = df.sort_values(['String', 'Integer'], ascending=[False, True])
df['rank'] = df.groupby(['String', 'Integer'], sort=False).ngroup().rank()
String Integer rank
7 c 4 2.0
8 c 4 2.0
9 c 4 2.0
6 c 6 4.0
4 b 1 5.0
5 b 3 6.0
0 a 1 7.0
1 a 2 8.0
2 a 3 9.5
3 a 3 9.5
我正在寻找一种基于多列生成排名的方法,其中一列包含字符串,另一列包含整数(可能很容易超过 2 列,但为了更容易,我限制为 2 列例如)。
import pandas as pd
df = pd.DataFrame(data={'String':['a','a','a','a','b','b','c','c','c','c'],'Integer':[1,2,3,3,1,3,6,4,4,4]})
print(df)
String Integer
0 a 1
1 a 2
2 a 3
3 a 3
4 b 1
5 b 3
6 c 6
7 c 4
8 c 4
9 c 4
我们的想法是能够创建排名,按字符串降序排列每行,整数按升序排列,这将是输出:
Rank String Integer
0 2 c 4
1 2 c 4
2 2 c 4
3 4 c 6
4 5 b 1
5 6 b 3
6 7 a 1
7 8 a 2
8 9.5 a 3
9 9.5 a 3
到目前为止,这是我设法做到的,但我在共享排名时如何生成 'average' 时遇到了问题。
df['concat_values'] = df['String'] + df['Integer'].astype(str)
df = df.sort_values(['String','Integer'],ascending=[False,True])
df = df.reset_index(drop=True).reset_index()
df['repeated'] = df.groupby('concat_values')['concat_values'].transform('count')
df['pre_rank'] = df['index'] + 1
df = df.sort_values('pre_rank')
df = df.drop('index',axis=1)
print(df)
String Integer concat_values repeated pre_rank
0 c 4 c4 3 1
1 c 4 c4 3 2
2 c 4 c4 3 3
3 c 6 c6 1 4
4 b 1 b1 1 5
5 b 3 b3 1 6
6 a 1 a1 1 7
7 a 2 a2 1 8
8 a 3 a3 2 9
9 a 3 a3 2 10
我想过使用一些过滤或公式,以便当 repeated
列的值大于 1 时,pre_rank
得到应用的函数 returns 平均值,但是该函数不能推广到所有行,它适用于第一行,但它会为第二行产生更高的值(因为 pre_rank
现在具有更高的值)。我相信我只是错过了完成它的最后一步,但无法解决。谢谢!
我的方法:
df = df.sort_values(['String','Integer'], ascending=[False, True])
df['rank'] = np.arange(len(df)) + 1
df['rank'] = df.groupby(['String', 'Integer'])['rank'].transform('mean')
输出:
String Integer rank
7 c 4 2.0
8 c 4 2.0
9 c 4 2.0
6 c 6 4.0
4 b 1 5.0
5 b 3 6.0
0 a 1 7.0
1 a 2 8.0
2 a 3 9.5
3 a 3 9.5
sort
+ ngroup
+ rank
.
需要您在 groupby 中指定 sort=False
,以便 ngroup
标签按照您排序的顺序生成。
df = df.sort_values(['String', 'Integer'], ascending=[False, True])
df['rank'] = df.groupby(['String', 'Integer'], sort=False).ngroup().rank()
String Integer rank
7 c 4 2.0
8 c 4 2.0
9 c 4 2.0
6 c 6 4.0
4 b 1 5.0
5 b 3 6.0
0 a 1 7.0
1 a 2 8.0
2 a 3 9.5
3 a 3 9.5