在一对多的数据框中计算时间差

3

我最近下载了我的英雄联盟数据。我有以下的数据框:

df = pd.DataFrame.from_dict({'DateTime': {
    0: 156102273400,
    1: 156101627200,
    2: 156092208200,
    3: 1559897767000,
    4: 1559890046000,
    5: 1559889968000},
                      'EventType': {
    0: 'LOGOUT_USER',
    1: 'LOGIN',
    2: 'LOGOUT_USER',
    3: 'LOGIN',
    4: 'LOGIN',
    5: 'LOGIN'}})

我得到了以下的数据框:

>>>df
Index    DateTime          EventType
0        156102273400      LOGOUT_USER
1        156101627200      LOGIN
2        156092208200      LOGOUT_USER
3        1559897767000     LOGIN
4        1559890046000     LOGIN
5        1559889968000     LOGIN

我希望将一个单独的LOGOUT_USER映射到下一个LOGOUT_USER之前的最小LOGIN。然后,我应该能够计算出总游戏时间。
理想输出如下:
>>>fixed_df
Index    DateTime          EventType
0        156102273400      LOGOUT_USER
1        156101627200      LOGIN
2        156092208200      LOGOUT_USER
3        1559889968000     LOGIN

日期时间在您的示例中是否总是按升序排序? - Erfan
4个回答

3

您可以执行

df.groupby(df.eventType.eq('LOGOUT_USER').cumsum()).agg(['first','last'])\
    .stack(level=1).reset_index(drop=True)
Out[634]: 
        dateTime    eventType
0   156102273400  LOGOUT_USER
1   156101627200        LOGIN
2   156092208200  LOGOUT_USER
3  1559889968000        LOGIN

看起来像是一个简单的idxmin问题 :) - cs95
这个方案也可行,不过我认为cs95的方案可能(主观上)更易读。 - Victor Nogueira

3

我认为你正在寻找 groupbyidxmin

grouper = df['EventType'].ne(df['EventType'].shift()).cumsum()
df.loc[df.groupby(grouper)['DateTime'].idxmin()]  

        DateTime    EventType
0   156102273400  LOGOUT_USER
1   156101627200        LOGIN
2   156092208200  LOGOUT_USER
5  1559889968000        LOGIN

这是一个好的解决方案。我想确认我的理解。第一行代码分配grouper的作用如下:创建一个组,其中pd.Series EventType不等于其直接下方的事件类型。这将把LOGOUT_USER分组到许多直接下方的LOGIN条目中。第二行对所有组的DateTime列求和,但由于我们使用了.idxmin(),因此这只会选择特定组的最小DateTime。这个逻辑正确吗? - Victor Nogueira
1
@VictorNogueira 所有连续的LOGOUT_USER和LOGIN用户行将被单独分组。您对idxmin的理解是完全正确的。 - cs95

0

没有groupby,你可以组合你的逻辑:

# logouts
log_out = df.eventType.eq('LOGOUT_USER')

# before login
next_log_in = df.eventType.shift(-1).eq('LOGIN')

# logout followed by login    
markers = log_out & next_log_in

# those logouts and logins after
df[markers | markers.shift()]

输出:

        dateTime    eventType
0   156102273400  LOGOUT_USER
1   156101627200        LOGIN
2   156092208200  LOGOUT_USER
3  1559897767000        LOGIN

0

你还可以设置一个额外的组标签g(加上EventType),然后在不运行groupby的情况下进行drop_duplicates

df.assign(g=df['EventType'].eq('LOGOUT_USER').cumsum()) \
  .drop_duplicates(['g','EventType'], keep='last') \
  .drop('g', axis=1)

#        DateTime    EventType
#0   156102273400  LOGOUT_USER
#1   156101627200        LOGIN
#2   156092208200  LOGOUT_USER
#5  1559889968000        LOGIN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接