熊猫排名与变换('排名')

时间:2016-11-04 11:45:55

标签: python pandas

我不确定这是一个错误还是一个功能,但我真的想了解它是如何工作的。

我有一个非常简单的数据集

In [0]: data
Out[0]:
  group  value  data
0     A      1     1
1     A      2     1
2     B      3     1
3     B      4     1

然后我有一些转变:

In [1]: data.groupby('group').transform('rank')
Out[1]:
   value  data
0    1.0   1.5
1    2.0   1.5
2    1.0   1.5
3    2.0   1.5

In [2]: data.groupby('group').value.transform('rank')
Out[2]:
0    1
1    1
2    2
3    2

In [3]: data.groupby('group').data.transform('rank')
Out[3]:
0    1.5
1    1.5
2    1.5
3    1.5

In [4]: data.groupby('group').transform('rank').value
Out[4]:
0    1.0
1    2.0
2    1.0
3    2.0

In [5]: data.groupby('group').value.rank()
Out[5]:
0    1.0
1    2.0
2    1.0
3    2.0

In [6]: data.groupby('group').cumcount()
Out[6]:
0    0
1    1
2    0
3    1

我发现奇怪的事情:

  • 第一个。虽然我似乎理解value列发生了什么(类似于第5和第6列)但我无法理解data列发生了什么。价值1.5来自哪里?
  • 第二个。它不是仅选择指定的列并应用类似于第一个的逻辑,而是完全改变了输出。我可以假设现在枚举组而不是组内的行,但我仍然不明白为什么它以这种奇怪的方式完成?
  • 第三个。它的行为完全符合预期,只是它选择了指定的列并应用了第一个相同的逻辑(与前一个相反)。但我仍然错过了这个价值的来源;
  • 第四个。难道这个与第二个不一样吗?
  • 第5和第6个看起来完全一样,但后者从0开始。它是否正确?

如果有人能向我解释,我将非常感激。

感谢。

2 个答案:

答案 0 :(得分:1)

让我更加混淆 - rank()方法有一个method参数......

默认:method='average'

In [70]: data.groupby('group').transform('rank')
Out[70]:
   value  data
0    1.0   1.5
1    2.0   1.5
2    1.0   1.5
3    2.0   1.5

In [71]: data.groupby('group').transform('rank', method='average')
Out[71]:
   value  data
0    1.0   1.5
1    2.0   1.5
2    1.0   1.5
3    2.0   1.5

方法:min

In [72]: data.groupby('group').transform('rank', method='min')
Out[72]:
   value  data
0    1.0   1.0
1    2.0   1.0
2    1.0   1.0
3    2.0   1.0

方法:max

In [73]: data.groupby('group').transform('rank', method='max')
Out[73]:
   value  data
0    1.0   2.0
1    2.0   2.0
2    1.0   2.0
3    2.0   2.0

方法:first

In [74]: data.groupby('group').transform('rank', method='first')
Out[74]:
   value  data
0    1.0   1.0
1    2.0   2.0
2    1.0   1.0
3    2.0   2.0

方法:dense

In [75]: data.groupby('group').transform('rank', method='dense')
Out[75]:
   value  data
0    1.0   1.0
1    2.0   1.0
2    1.0   1.0
3    2.0   1.0

来自docs

  

方法:{averageminmaxfirstdense}

     

平均值:组的平均排名

     

min:组中的最低排名

     

max:群组中的最高排名

     

首先:按照它们出现在数组中的顺序分配

     

密集:像'min',但是组之间的等级总是增加1

还有另一个参数:

  

pct :布尔值,默认为False

     

计算数据的百分比等级

答案 1 :(得分:0)

在更高版本的熊猫(我的是0.24.2)中,data.groupby('group').transform('rank')data.groupby('group').value.transform('rank')的行为如下:

In [1]: data.groupby('group').transform('rank')
Out[1]:
   value  data
0    1.0   1.5
1    1.0   1.5
2    2.0   1.5
3    2.0   1.5

In [2]: data.groupby('group').value.transform('rank')
Out[2]:
0    1
1    1
2    2
3    2

回答您的问题:

  • 第1个和第3个:method函数的默认rank()average,因此,数据列的排名为1.5(最小值= 1,最大值= 2,平均值= 1.5)
  • 第二和第四:在更高版本的熊猫中,data.groupby('group').transform('rank').value返回的内容与data.groupby('group').value.transform('rank')相同。我建议不要同时使用transform()rank() data.groupby('group').value.rank()正是您应该使用的。如果您查看rank()函数中的source code。它已经实现了transform()的逻辑:广播到整个列。如果最终使用了transform('rank'),则rank函数仍会起作用,但是transform会混乱。这是源代码的简化版本:

    import pandas as pd
    import pandas.core.algorithms as algorithms
    
    g = data.groupby('group')
    result = getattr(g, 'rank')() #same as g.rank()
    ids = g.grouper.group_info[0] #array([0, 0, 1, 1])
    
    output = []
    for i, _ in enumerate(result.columns):
        res = algorithms.take_1d(result.iloc[:, i].values, ids)
        output.append(res) 
        #[array([1., 1., 2., 2.]), array([1.5, 1.5, 1.5, 1.5])]
    pd.DataFrame._from_arrays(output, columns=result.columns, index=g.obj.index)
    #value|data
    #  1  | 1.5
    #  1  | 1.5
    #  2  | 1.5
    #  2  | 1.5
    
  • 第5位和第6位:cumcount()从0到该组的长度-1,rank()从1到n。

希望这会有所帮助。