在使用python / pandas DataFrame计算值之前验证行

时间:2014-01-20 03:58:40

标签: python data-structures pandas

我是python和pandas的新手,在尝试了几种方法之后,我希望根据我的分析目标,就构建此数据集的最佳方法提出一些建议。

鉴于以下DataFrame

id          event          timestamp
1   "page 1 load"   1/1/2014 0:00:01
1   "page 1 exit"   1/1/2014 0:00:31
2   "page 2 load"   1/1/2014 0:01:01
2   "page 2 exit"   1/1/2014 0:01:31
3   "page 3 load"   1/1/2014 0:02:01
3   "page 3 exit"   1/1/2014 0:02:31
4   "page 1 load"   2/1/2014 1:00:01
4   "page 1 exit"   2/1/2014 1:00:31
5   "page 2 load"   2/1/2014 1:01:01
5   "page 2 exit"   2/1/2014 1:01:31
6   "page 3 load"   2/1/2014 1:02:01
6   "page 3 exit"   2/1/2014 1:02:31

这里的目标是计算从加载到退出所经过的时间。但是,我首先需要在计算经过的时间之前验证加载和退出时间戳确实来自同一会话(id)。我想到的方法是处理源数据集并创建一个新的DataFrame,其中每一行都是已经验证的数据的组合,添加一个已用过的列,使计算和分组更容易,就像这样。

id      event_1          timestamp_1        event_2       timestamp_2   elapsed
1   "page 1 load"   1/1/2014 0:00:01    "page 1 exit"    1/1/2014 0:00:31   0:00:30
2   "page 2 load"   1/1/2014 0:01:01    "page 2 exit"    1/1/2014 0:01:31   0:00:30
3   "page 3 load"   1/1/2014 0:02:01    "page 3 exit"    1/1/2014 0:02:31   0:00:30

如果这是一个好方法?如果是这样,创建这个新DataFrame的最佳方法是什么?

1 个答案:

答案 0 :(得分:4)

我会考虑将事件分成单独的列,例如使用str.extract

In [11]: df['event'].str.extract('page (?P<page>\d+) (?P<event>\w+)')
Out[11]: 
   page event
0     1  load
1     1  exit
2     2  load
3     2  exit
4     3  load
5     3  exit
6     1  load
7     1  exit
8     2  load
9     2  exit
10    3  load
11    3  exit

[12 rows x 2 columns]

如果将其设置为列:

In [12]: df[['page', 'event']] = df['event'].str.extract('page (?P<page>\d+) (?P<event>\w+)')

In [13]: df
Out[13]: 
    id event           timestamp page
0    1  load 2014-01-01 00:00:01    1
1    1  exit 2014-01-01 00:00:31    1
2    2  load 2014-01-01 00:01:01    2
3    2  exit 2014-01-01 00:01:31    2
4    3  load 2014-01-01 00:02:01    3
5    3  exit 2014-01-01 00:02:31    3
6    4  load 2014-02-01 01:00:01    1
7    4  exit 2014-02-01 01:00:31    1
8    5  load 2014-02-01 01:01:01    2
9    5  exit 2014-02-01 01:01:31    2
10   6  load 2014-02-01 01:02:01    3
11   6  exit 2014-02-01 01:02:31    3

[12 rows x 4 columns]

我认为现在更容易推理......

然后你可以通过会话ID和页面进行分组:

In [14]: g = df.groupby(['id', 'page'])  # perhaps use as_index=False

获得所需结果的一种方法是使用例如通过以下功能:

def get_load_and_exit(x):
    assert len(x) == 2  # otherwise, logic should be about pairs (?)
    return pd.Series(x['timestamp'].values, x['event'])

In [16]: res = g.apply(get_load_and_exit)

In [17]: res
Out[17]: 
event                  load                exit
id page                                        
1  1    2014-01-01 00:00:01 2014-01-01 00:00:31
2  2    2014-01-01 00:01:01 2014-01-01 00:01:31
3  3    2014-01-01 00:02:01 2014-01-01 00:02:31
4  1    2014-02-01 01:00:01 2014-02-01 01:00:31
5  2    2014-02-01 01:01:01 2014-02-01 01:01:31
6  3    2014-02-01 01:02:01 2014-02-01 01:02:31

[6 rows x 2 columns]

假设这些是时间戳*,您可以简单地减去列:

In [18]: res['duration'] = res['exit'] - res['load']

In [19]: res
Out[19]: 
event                  load                exit  duration
id page                                                  
1  1    2014-01-01 00:00:01 2014-01-01 00:00:31  00:00:30
2  2    2014-01-01 00:01:01 2014-01-01 00:01:31  00:00:30
3  3    2014-01-01 00:02:01 2014-01-01 00:02:31  00:00:30
4  1    2014-02-01 01:00:01 2014-02-01 01:00:31  00:00:30
5  2    2014-02-01 01:01:01 2014-02-01 01:01:31  00:00:30
6  3    2014-02-01 01:02:01 2014-02-01 01:02:31  00:00:30

[6 rows x 3 columns]

*值得确保timestamp列实际上是一个datetime列(atm不是!):

df['timestamp'] = pd.to_datetime(df['timestamp'])