本文通過一個簡單的實例,介紹了一下pandas中rank()函數(shù)的用法扫尺。
一、問題:
在一張成績表中炊汤,有班級正驻、姓名、成績?nèi)星栏敲慈绾卫肞ython篩選出每個班級中的排名第二的學(xué)生信息姑曙?
解決這個問題,有兩個關(guān)鍵點:第一迈倍,要進(jìn)行分組計算伤靠,根據(jù)班級進(jìn)行分組;第二啼染,計算排名宴合,在每個組中計算排名,最后篩選出排名為第二的學(xué)生信息迹鹅。
二卦洽、排序問題
?? ? ? 在計算排名的場景中,對相同的成績(例如:上圖1斜棚,一班中的李四和王五同學(xué)的成績都是30分)該如何處理它們阀蒂?本人認(rèn)為该窗,一般會有三種處理方法:
(下面的介紹中,如無特別說明蚤霞,均以上表中的1班的同學(xué)的成績作為示例數(shù)據(jù))
順序排名酗失,成績相同時,誰在前争便,誰排名靠前(有點先到先得的意思)级零;
? ? ? ? ? ? ? ? ? 圖2,順序排名中滞乙,李四和王五成績都為30奏纪,但是李四在前,所以李四排名為2斩启,而王五排名為3序调,整體的名次為1,2兔簇,3发绢,4,5
跳躍排名垄琐,成績相同時边酒,排名相同,其他元素按其‘位置’排名(可參考順序排名)狸窘;
? ? ? ? ? ? ? ? ? 圖2墩朦,跳躍排名中,李四和王五的成績都為30翻擒,且排名都為2氓涣,但后面同學(xué)劉三、趙柳都按其出現(xiàn)位置進(jìn)行了排名陋气,排名分別為4和5劳吠,整體的名次,產(chǎn)生了跳躍巩趁,沒有名次為第3的了痒玩,整體名次為:1,2晶渠,2凰荚,4,5
密集排名褒脯,成績相同時,排名相同缆毁,其他同學(xué)依次累加(+1)番川。
? ? ? ? ? ? ? ? 圖2,密集排名中,雖然李四和王五的成績相同颁督,排名相同践啄,但后面劉三、趙柳同學(xué)都按次序依次進(jìn)行了排名(+1)沉御,其整體的名次沒有跳躍屿讽,變?yōu)?,2吠裆,2伐谈,3,4
示例如下:
? ? ? ? 那么试疙,在Python中如何實現(xiàn)上述三種類型的排名诵棵,可以利用三方庫pandas中的rank方法,可以通過設(shè)置rank()函數(shù)中method參數(shù)很方便的實現(xiàn)祝旷。
rank()函數(shù):
DataFrame.rank(axis=0,method='average',numeric_only=None,na_option='keep',ascending=True,pct=False)
? ? ? 用途:沿著某個軸(0或者1)計算對象的排名
? ? ? Returns:以Series或者DataFrame的類型返回數(shù)據(jù)的排名(哪個類型調(diào)用返回哪個類型)
? ? 包含有6個參數(shù):
?? ? ? ? axis:設(shè)置沿著哪個軸計算排名(0或者1)
? ? ? ? numeric_only:是否僅僅計算數(shù)字型的columns履澳,布爾值
?? ? ? ? na_option:NaN值是否參與排序及如何排序(‘keep’,‘top'怀跛,’bottom')
?? ? ? ? ascending:設(shè)定升序排還是降序排
?? ? ? ? pct:是否以排名的百分比顯示排名(所有排名與最大排名的百分比)
? ? ? ? 這里重點研究一下method參數(shù)? :?
? ? ? ? 在本小節(jié)的開頭距贷,介紹了排名問題中的三個一般情況,即順序排名吻谋、跳躍排名忠蝗、密集排名,在rank()函數(shù)可以通過設(shè)置method的值實現(xiàn)上述三種排名。?
method:取值可以為'average'住诸,'first'骑祟,'min', 'max'闽撤,'dense',這里重點介紹一下first脯颜、min哟旗、dense
"first": 顧名思義,第一個栋操,誰出現(xiàn)的位置靠前闸餐,誰的排名靠前。李四和王五的成績都為30矾芙,但是李四出現(xiàn)在王五的前面舍沙,所以李四的排名靠前(當(dāng)method取值為min,max剔宪,average時拂铡,都是要參考“順序排名”的)
df['順序排名'] = df.成績.rank(method='first',ascending=False)
? "min": 當(dāng)method=“min”時壹无,成績相同的同學(xué),取在順序排名中最小的那個排名作為該值的排名感帅,李四和王五同學(xué)排名分別為2和3斗锭,那么當(dāng)method為min時,取2和3的最小的那個作為第2名作為成績30的排名失球。
df['跳躍排名'] = df.成績.rank(method='min',ascending=False)
? "dense": 是密集的意思岖是,即相同成績的同學(xué)排名相同,其他依次加1即可实苞。
df['密集排名'] = df.成績.rank(method='dense',ascending=False)
備注:
關(guān)于average豺撑,成績相同時,取順序排名中所有名次之和除以該成績的個數(shù)硬梁,即為該成績的名次前硫;比如上述排名中,30排名為2,3荧止,那么 30的排名 = (2+3)/2=2.5屹电,成績?yōu)?0的同學(xué)只有1個,且排名為1跃巡,那50的排名就位1/1=1危号。
?關(guān)于max,和min一樣也是跳躍排名的一種素邪,成績相同時取順序排名中排名最大的作為該成績的名次外莲,在順序排名中,30最大的排名為3兔朦,那么當(dāng)參數(shù)為max時偷线,30的排名=3,此時沽甥,李四和王五的排名都為第3名了声邦。
例子:
? ? ? 如果不區(qū)分班級,對所有同學(xué)的成績進(jìn)行排名摆舟,不同的method值亥曹,排名情況如下:
三、代碼
rank()函數(shù)介紹完了恨诱,怎么樣利用rank()函數(shù)得到各個班級排名為第二名的學(xué)生信息呢媳瞪?
這里采用密集排名,完整代碼如下
def get_second(x):? ? return x[x.成績.rank(method='dense', ascending=False) == 2.0]df.groupby('班級').apply(get_second).reset_index(drop=True)
以上就是關(guān)于rank()函數(shù)的一點小小的用法照宝,若有錯誤蛇受,望指正