【问题标题】:how to split time into hours?如何将时间分成几个小时?
【发布时间】:2020-12-03 07:45:09
【问题描述】:

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

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
.
.
.

【问题讨论】:

  • 我的建议对你有什么效果?

标签: python pandas


【解决方案1】:

您真的希望最终输出列是实际小时数还是仅以小时形式显示原始数据?如果是后者,这应该可以工作

# Melt down DataFrame
df = df.melt(id_vars='UserID',var_name='Page',value_name='Seconds')

  UserID Page   Seconds
0   24  Page1   2789
1   39  Page1   3745
2   35  Page1   100
3   24  Page2   2375
4   39  Page2   3800
5   35  Page2   300
6   24  Page3   574
7   39  Page3   4567
8   35  Page3   1005

# Create column of Seconds converted to Hours
df['Hours'] = df['Seconds'] / 60

# Convert float to int data type
df['Hours'] = df['Hours'].astype(int)

UserID  Page    Seconds Hours
0   24  Page1   2789    46
1   39  Page1   3745    62
2   35  Page1   100     1
3   24  Page2   2375    39
4   39  Page2   3800    63
5   35  Page2   300     5
6   24  Page3   574     9
7   39  Page3   4567    76
8   35  Page3   1005    16

# Create new DataFrame of pivoted df DataFrame
df_hrs = df.pivot_table(index=['UserID'],columns=['Page'], values='Hours')

# Reset index to flatten DataFrame
df_hrs.reset_index(inplace=True)

# Change column name attribute
df_hrs.columns.rename('',inplace=True)

 UserID Page1   Page2   Page3
0   24   46     39      9
1   35   1      5       16
2   39   62     63      76

【讨论】:

  • 谢谢,但这不起作用。我想知道用户在第一个小时、第二个小时、第三个小时等期间在哪个页面上。
  • @MohammadAlshehri 用户打开和关闭每个页面的开始和停止时间列在哪里?您的问题仅提供了用户在页面上停留的时间(以秒为单位)。
  • 我不知道用户何时进入和离开每个页面的时间戳,我只知道他们在每个页面上花费了多长时间(以秒为单位)。
【解决方案2】:

解决方案要点:

(答案末尾有完整代码)

# 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

一些细节

我最近遇到了类似的挑战,并且在How to handle ValueError: Index contains duplicate entries using df.pivot or pd.pivot_table? 上也得到了一些很好的建议,这些建议在这里也应该有用。在你的特殊情况下,我会这样处理:

  1. 通过df.cumsum()获取累计时间,
  2. 使用df / (60*60) 将秒转换为小时,
  3. 使用带有df.astype(int) 的整数关注完整小时数,
  4. 重塑您的 df,以便使用 pd.melt() 进行更轻松的计算,然后
  5. 通过pd.crosstab()获得最终形式

结果一:

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。在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 仍然有一个 NaN 用于 '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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    相关资源
    最近更新 更多