Pandas 根据几列进行排名

3kt*_*3kt 4 python python-3.x pandas

我有以下数据框:

event_id  occurred_at  user_id
   19148   2015-10-01        1
   19693   2015-10-05        2
   20589   2015-10-12        1
   20996   2015-10-15        1
   20998   2015-10-15        1
   23301   2015-10-23        2
   23630   2015-10-26        1
   25172   2015-11-03        1
   31699   2015-12-11        1
   32186   2015-12-14        2
   43426   2016-01-13        1
   68300   2016-04-04        2
   71926   2016-04-19        1
Run Code Online (Sandbox Code Playgroud)

我想按时间顺序(1 到 n)对每个用户的事件进行排名。

我可以通过这样做来实现这一点:

df.groupby('user_id')['occurred_at'].rank(method='dense')
Run Code Online (Sandbox Code Playgroud)

但是,对于同一日期(同一用户)发生的这两行,我最终得到相同的排名:

   20996   2015-10-15        1
   20998   2015-10-15        1
Run Code Online (Sandbox Code Playgroud)

如果事件日期相同,我想比较event_id并任意排名最低的事件event_id。我怎样才能轻松实现这一目标?

我可以对排名进行后期处理,以确保每个排名仅使用一次,但这看起来相当庞大......

编辑:如何重现:

将数据复制粘贴到data.csv文件中。然后 :

import pandas as pd
df = pd.read_csv('data.csv', delim_whitespace=True)
df['rank'] = df.groupby('user_id')['occurred_at'].rank(method='dense')
>>> df[df['user_id'] == 1]
    event_id occurred_at  user_id  rank
0      19148  2015-10-01        1   1.0
2      20589  2015-10-12        1   2.0
3      20996  2015-10-15        1   3.0 <--
4      20998  2015-10-15        1   3.0 <--
6      23630  2015-10-26        1   4.0
7      25172  2015-11-03        1   5.0
8      31699  2015-12-11        1   6.0
10     43426  2016-01-13        1   7.0
12     71926  2016-04-19        1   8.0
Run Code Online (Sandbox Code Playgroud)

我使用 python3 和 pandas 0.18.1

piR*_*red 5

sort_values('event_id')在分组之前然后传递method='first'rank

另请注意,如果occurred_at还没有datetime,请制作datetime

# unnecessary if already datetime, but doesn't hurt to do it anyway
df.occurred_at = pd.to_datetime(df.occurred_at) 

df['rank'] = df.sort_values('event_id') \
                 .groupby('user_id').occurred_at \
                 .rank(method='first')
df
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


完整可验证代码参考

from StringIO import StringIO
import pandas as pd

text = """event_id  occurred_at  user_id
   19148   2015-10-01        1
   19693   2015-10-05        2
   20589   2015-10-12        1
   20996   2015-10-15        1
   20998   2015-10-15        1
   23301   2015-10-23        2
   23630   2015-10-26        1
   25172   2015-11-03        1
   31699   2015-12-11        1
   32186   2015-12-14        2
   43426   2016-01-13        1
   68300   2016-04-04        2
   71926   2016-04-19        1"""

df = pd.read_csv(StringIO(text), delim_whitespace=True)

df.occurred_at = pd.to_datetime(df.occurred_at) 

df['rank'] = df.sort_values('event_id').groupby('user_id').occurred_at.rank(method='first')

df
Run Code Online (Sandbox Code Playgroud)