【问题标题】:Convert Pandas dataframe row containing datetime range along to new dataframe with a row for each date along with hours included on that date将包含日期时间范围的 Pandas 数据框行转换为新的数据框,每个日期都有一行以及该日期包含的小时数
【发布时间】:2019-02-12 17:54:21
【问题描述】:

所以,我的数据框中有 StartDateTime 和 EndDateTime 列,我想为日期时间范围内的每个日期生成一个新的数据框,但我还想要包含在该日期的小时数日期范围。

In [11]: sessions = pd.DataFrame({'Start':['2018-01-01 13:00:00','2018-03-01 16:30:00'],
'End':['2018-01-03 07:00:00','2018-03-02 06:00:00'],'User':['Dan','Fred']})
In [12]: sessions
Out[12]:    
                Start                 End User
0 2018-01-01 13:00:00 2018-01-03 07:00:00  Dan 
1 2018-03-01 16:30:00 2018-03-02 06:00:00 Fred 

所需的数据框:

Date        Hours   User
2018-01-01  11      Dan
2018-01-02  24      Dan
2018-01-02  7       Dan
2018-03-01  7.5     Fred
2018-03-02  6       Fred

我见过很多例子,它们只是为日期范围内的每个日期生成了一个数据框(例如Expanding pandas data frame with date range in columns) 但范围内包含的每个日期的小时数的附加字段没有任何内容。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我不知道这是最干净的解决方案,但它似乎有效。

    In [13]: sessions = pd.DataFrame({'Start':['2018-01-01 13:00:00','2018-03-01 16:30:00'],
    'End':['2018-01-03 07:00:00','2018-03-02 06:00:00'],'User':['Dan','Fred']})
    

    将开始和结束转换为日期时间

    In [14]: sessions['Start']=pd.to_datetime(sessions['Start'])
        sessions['End']=pd.to_datetime(sessions['End'])
    

    为范围内的每个日期创建一行

    In [15]: dailyUsage = pd.concat([pd.DataFrame({'Date': 
    pd.date_range(pd.to_datetime(row.Start).date(), row.End.date(), freq='D'),'Start':row.Start,
                   'User': row.User,
                   'End': row.End}, columns=['Date', 'Start','User', 'End']) 
               for i, row in sessions.iterrows()], ignore_index=True)
    

    根据开始日期时间、结束日期时间和特定日期计算日期小时数的函数

    In [16]: def calcDuration(x):
        date=  x['Date']
        startDate = x['Start']
        endDate = x['End']
    
        #starts and stops on same day
        if endDate.date() == startDate.date():
            return (endDate - startDate).seconds/3600
    
        #this is on the start date
        if (date.to_pydatetime().date() - startDate.date()).days == 0:
            return 24 - startDate.hour
    
        #this is on the end date
        if (date.to_pydatetime().date() - endDate.date()).days == 0:
            return startDate.hour
    
        #this is on an interior date
        else:
            return 24
    

    计算每个日期的小时数

    In [17]: dailyUsage['hours'] = dailyUsage.apply(calcDuration,axis=1)
    
    In [18]: dailyUsage.drop(['Start','End'],axis=1).head()
    Out [18]: 
            Date User  hours
    0 2018-01-01  Dan     11 
    1 2018-01-02  Dan     24 
    2 2018-01-03  Dan     13 
    3 2018-03-01 Fred      8 
    4 2018-03-02 Fred     16 
    

    【讨论】:

      【解决方案2】:

      如果您不介意整数,类似的方法也可以;

      df['date'] = df['Date'].dt.date
      gb = df.groupby(['date', 'User'])['Date'].size()
      print(gb)
      
      date        User
      2018-01-01  Dan     11
      2018-01-02  Dan     24
      2018-01-03  Dan      8
      2018-03-01  Fred     8
      2018-03-02  Fred     6
      Name: Date, dtype: int64
      

      【讨论】:

        猜你喜欢
        • 2021-05-09
        • 1970-01-01
        • 2016-08-14
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        • 2022-09-27
        • 2021-11-23
        • 1970-01-01
        相关资源
        最近更新 更多