首页 > 解决方案 > 如何将时间分成几个小时?

问题描述

我有一个数据框,其中包含用户在某个网页(任务)上花费的秒数,如下所示:

UserID  Page1   Page2   Page3 ....
24      2789    2375    574 
39      3745    3800    4567
35      100     300     1005
.
.
.

我想将这些秒分成几个小时,如下所示,这样我就可以知道每个用户在他/她导航网站的某个小时内在哪个页面上:

UserID  Hour1     Hour2     Hour3  ....
24      Page1     Page1     Page2 
39      Page1     Page2     Page3
35      Page1     Page1     Page1
.
.
.

标签: pythonpandas

解决方案


解决方案要点:

(完整代码在答案末尾)

# reshape
dfm = pd.melt(df, id_vars=['UserID'], value_vars=df.columns[1:])

# rename
dfm.columns = ['UserID', 'variable', 'hour']

# crosstab into final form
df_ct = pd.crosstab(dfm['UserID'],dfm['hour'],dfm['variable'],aggfunc='last')

输出

hour        1      2      3      4
UserID                            
24      Page1  Page3    NaN    NaN
35      Page3    NaN    NaN    NaN
39        NaN  Page1  Page2  Page3

一些细节

我最近遇到了类似的挑战,并且在如何处理 ValueError 方面也得到了一些很好的建议:索引包含使用 df.pivot 或 pd.pivot_table 的重复条目?这在这里也应该证明是有用的。在您的特定情况下,我会这样处理:

  1. 获得累积时间df.cumsum()
  2. 将秒转换为小时df / (60*60)
  3. 专注于使用整数的完整小时数df.astype(int)
  4. 重塑你df的更容易计算pd.melt(),然后
  5. 获得最终形式pd.crosstab()

结果1:

hour        0      1      2      3
UserID                            
24      Page1  Page3    NaN    NaN
35      Page3    NaN    NaN    NaN
39        NaN  Page1  Page2  Page3

然后由您决定如何呈现信息。就目前而言,User 24完成Page1 before an hour had passed,并Page2 and Page3在第二个小时开始之前完成。将时间从 0 开始可能会感觉更自然1。在这种情况下,只需包括

df = df + 1

在最初的步骤中获得:

结果 2:小时开始于1

hour        1      2      3      4
UserID                            
24      Page1  Page3    NaN    NaN
35      Page3    NaN    NaN    NaN
39        NaN  Page1  Page2  Page3

而现在这一切都只是一个问题,如何处理NaNs. 您可以包括.fill()

d.crosstab(dfm['UserID'],dfm['hour'],dfm['variable'],aggfunc='last')#.ffill(axis=1)

并得到:

结果3:照顾NaNs

hour        1      2      3      4
UserID                            
24      Page1  Page3  Page3  Page3
35      Page3  Page3  Page3  Page3
39        NaN  Page1  Page2  Page3

User 39仍然有一个NaNfor 'Hour1,但我会等待你对你想用那个做什么的反馈。

完整代码:

# imports
import pandas as pd

# data
df_i = pd.DataFrame({'UserID': {0: 24, 1: 39, 2: 35},
                     'Page1': {0: 2789, 1: 3745, 2: 100},
                     'Page2': {0: 2375, 1: 3800, 2: 300},
                     'Page3': {0: 574, 1: 4567, 2: 1005}}).set_index('UserID')

# time conversion
df = df_i.cumsum(axis = 1)
df = df / (60*60)
df = df.astype(int)
df = df + 1
df = df.reset_index()

# reshape
dfm = pd.melt(df, id_vars=['UserID'], value_vars=df.columns[1:])

# rename
dfm.columns = ['UserID', 'variable', 'hour']

# crosstab into final form
df_ct = pd.crosstab(dfm['UserID'],dfm['hour'],dfm['variable'],aggfunc='last').ffill(axis=1)
df_ct
# df

推荐阅读