Pandas合并用户登录和注销时间



我是Pandas的新手,正在尝试计算屏幕时间。基本上是用户在工作站上解锁屏幕的时间。数据如下:

User    Action  ActionTime
0   User1   logon   1/1/2020 8:00
1   User1   lock    1/1/2020 12:00
2   User1   unlock  1/1/2020 13:00
3   User1   logoff  1/1/2020 16:00

现在我正试图将登录操作(登录和解锁(和注销操作(注销和锁定(合并到带有时间戳的单行上。示例:

Action_x ActionTime_x   Action_y    ActionTime_y
User                
User1   logon   1/1/2020 8:00   lock    1/1/2020 12:00
User1   unlock  1/1/2020 13:00  logoff  1/1/2020 16:00

为了实现这一点,我尝试将登录和注销操作放入它们自己的数据帧中,然后尝试将它们合并在一起。

logon = df[df["Action"].isin(["logon","unlock"])]
logon.set_index("User", inplace= True)
logoff = df[df["Action"].isin(["logoff","lock"])]
logoff.set_index("User", inplace= True)
merged = pd.merge(logon, logoff, right_index=True, left_index=True)

我在输出中得到的是:

Action_x ActionTime_x   Action_y ActionTime_y
User                
User1   logon   1/1/2020 8:00   lock    1/1/2020 12:00
User1   logon   1/1/2020 8:00   logoff  1/1/2020 16:00
User1   unlock  1/1/2020 13:00  lock    1/1/2020 12:00
User1   unlock  1/1/2020 13:00  logoff  1/1/2020 16:00

很明显,关于合并,我还有很多东西要学。合并后是否可以执行此操作,或者我遗漏了什么。

编辑:在本例中,User是我的数据帧索引。

与其合并,不如采用另一种方法:

  1. 若要为每个用户获得单独的结果,请对DataFrame进行分组用户

  2. 对每组行(针对特定用户(应用一个函数其中:

    • Action.isin(['logon','unlock'].cumsum((执行二级分组。这样,登录解锁操作中的每一行都会启动一个新组(实际上由2行组成,第二行在这对中是关于注销的行(
    • 每个此类组的结果应包含:
      • 登录操作-第一行的操作
      • 开始-从第一行开始的ActionTime
      • 注销操作-最后一行的操作
      • 停止最后一行的ActionTime

这样做的代码是:

  1. 定义要应用于每组行的函数对于当前用户:

    def act(grp):
    return grp.sort_values('ActionTime').groupby(grp.Action.isin(['logon', 'unlock'])
    .cumsum()).agg(**{'Login Action': ('Action', 'first'),
    'Start': ('ActionTime', 'first'), 'Logoff Action': ('Action', 'last'),
    'Stop': ('ActionTime', 'last')})
    

    为了在列名中有空格,我使用了字典拆包

  2. 将其应用于每组:

    result = df.groupby('User').apply(act).reset_index(level=1, drop=True)
    

    附加元素是删除不必要的索引级别。

为了提供一个更具指导性的例子,我创建了DataFrame(适用于2个用户(为:

User  Action          ActionTime
0  User1   logon 2020-01-01 08:00:00
1  User1    lock 2020-01-01 12:00:00
2  User1  unlock 2020-01-01 13:00:00
3  User1  logoff 2020-01-01 16:00:00
4  User2   logon 2020-01-01 08:15:00
5  User2    lock 2020-01-01 08:17:00
6  User2  unlock 2020-01-01 09:22:00
7  User2  logoff 2020-01-01 09:35:00

我的代码的结果是:

Login Action               Start Logoff Action                Stop
User                                                                    
User1        logon 2020-01-01 08:00:00          lock 2020-01-01 12:00:00
User1       unlock 2020-01-01 13:00:00        logoff 2020-01-01 16:00:00
User2        logon 2020-01-01 08:15:00          lock 2020-01-01 08:17:00
User2       unlock 2020-01-01 09:22:00        logoff 2020-01-01 09:35:00

我假设您的DataFrameActionTime排序,或者全局或至少针对每个用户(实际上,按userActionTime,所以我没有包含任何排序。如果不满足此条件,请添加排序,例如在act函数中:

return grp.sort_values('ActionTime').groupby(...)

最新更新