如何从登录和注销表中识别并发用户?

时间:2017-12-20 14:46:50

标签: python audit-logging

下表显示了给定软件的登录和注销时间。

USER_NAME USER_ROLE GMT_LOGIN_TIME      GMT_LOGOUT_TIME       LOGIN_DURATION 
ABCD      SUP_235   2017-12-15 11:05:25 2017-12-15 11:09:01           216.0
ABCE      SUP_235   2017-12-15 11:23:14 2017-12-15 11:33:17           603.0
ABCF      USER_285  2017-12-15 11:44:12 2017-12-15 12:07:52          1420.0
ABCG      SUP_230   2017-12-15 18:43:17 2017-12-15 19:00:20          1023.0
ABCH      USER_245  2017-12-15 10:36:59 2017-12-15 11:42:00          3901.0

如何识别并发用户?我将不得不在Python中执行此操作,但我并不担心该编程语言中的实现。我想了解逻辑本身。

在上面的示例中,用户ABCD,ABCE和ABCH是唯一的同步。

1 个答案:

答案 0 :(得分:1)

以下是使用pandas

执行此操作的方法
from StringIO import StringIO

# read data into dataframe
data = StringIO("""USER_NAME,USER_ROLE,GMT_LOGIN_TIME,GMT_LOGOUT_TIME,LOGIN_DURATION 
ABCD,SUP_235,2017-12-15 11:05:25,2017-12-15 11:09:01,216.0
ABCE,SUP_235,2017-12-15 11:23:14,2017-12-15 11:33:17,603.0
ABCF,USER_285,2017-12-15 11:44:12,2017-12-15 12:07:52,1420.0
ABCG,SUP_230,2017-12-15 18:43:17,2017-12-15 19:00:20,1023.0
ABCH,USER_245,2017-12-15 10:36:59,2017-12-15 11:42:00,3901.0""")
df = pd.read_csv(data, sep=",")

# create a new column for simultaneous
df['simultaneous'] = 0

# loop through dataframe and check condition
for i in df.index:
    login, logout = df.loc[i,'GMT_LOGIN_TIME'], df.loc[i,'GMT_LOGOUT_TIME']
    this_index = df.index.isin([i])
    df.loc[i, 'simultaneous'] = int(any(
        (df[~this_index]['GMT_LOGIN_TIME'] <= logout) & (df[~this_index]['GMT_LOGOUT_TIME'] >= login)
    ))

输出:

  USER_NAME USER_ROLE       GMT_LOGIN_TIME      GMT_LOGOUT_TIME  \
0      ABCD   SUP_235  2017-12-15 11:05:25  2017-12-15 11:09:01   
1      ABCE   SUP_235  2017-12-15 11:23:14  2017-12-15 11:33:17   
2      ABCF  USER_285  2017-12-15 11:44:12  2017-12-15 12:07:52   
3      ABCG   SUP_230  2017-12-15 18:43:17  2017-12-15 19:00:20   
4      ABCH  USER_245  2017-12-15 10:36:59  2017-12-15 11:42:00   

   LOGIN_DURATION   simultaneous  
0            216.0             1  
1            603.0             1  
2           1420.0             0  
3           1023.0             0  
4           3901.0             1  

这是正确的,因为ABCDABCE都与ABCH同时发生。

逻辑解释:

  1. 我们遍历数据框的每个index(行)并抓取该用户的loginlogout次。

  2. 接下来,我们要检查所有其他行的重叠,因此我们创建this_index作为索引器以指向当前行。使用按位反转运算符(~),我们可以选择df[~this_index]的其他行。

  3. 对于其他行,我们使用any函数检查其中是否有任何行符合overlap condition。由于这会返回boolean,我们会转换为int。如果您想查看有多少其他连接与此重叠,我们也可以使用sum(condition)

  4. int(any(condition))的结果放在'simultaneous'列中。

  5. 有关重叠时间范围背后的逻辑,请参阅此页:  Determine Whether Two Date Ranges Overlap

    编辑:更多的熊猫方式

    对于大型表,在pandas中循环遍历的速度很慢。这是一种使用pandas.Dataframe.apply()获得相同结果的方法,它应该更快。

    df['simultaneous'] = df.apply(
        lambda x: int(
            any(
                (df[df['USER_NAME'] != x['USER_NAME']]['GMT_LOGIN_TIME'] <= x['GMT_LOGOUT_TIME']) &\
                (df[df['USER_NAME'] != x['USER_NAME']]['GMT_LOGOUT_TIME'] >= x['GMT_LOGIN_TIME'])
            )
        ),
        axis=1
    )