我是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
的最佳方法是什么?
答案 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'])