首页 文章

计算pandas Dataframe中的日期时间差异

提问于
浏览
2

我有以下数据帧:

data = [
("10/10/2016","A"),
("10/10/2016","B"),
("09/12/2016","B"),
("09/12/2016","A"),
("08/11/2016","A"),
("08/11/2016","C")] 

#Create DataFrame base
df = pd.DataFrame(data, columns=("Time","User"))

# Convert time column to correct format for time calculations
df["Time"] = pd.to_datetime(df["Time"], '%m/%d/%Y')

每行表示用户何时进行特定操作 . 我想计算 each 用户执行该特定操作的频率(以天为单位) .

假设用户A在2016年11月8日第一次交易,然后他在2016年12月9日再次交易,即大约30天后交易 . 然后,他在第二次交易后大约29天后于2016年10月10日再次交易 . 因此,他的平均频率为(29 30)/ 2 .

最有效的方法是什么?

提前致谢!


  • 更新

我编写了以下函数来计算我想要的输出 .

from datetime import timedelta

def averagetime(a):
    numdeltas = len(a) - 1
    sumdeltas = 0

    i = 1
    while i < len(a):
        delta = abs((a[i] - a[i-1]).days)
        sumdeltas += delta
        i += 1

    if numdeltas > 1:
        avg = sumdeltas / numdeltas
    else:
        avg = 'NaN'  
    return avg

它正常工作,例如,当我传递整个“时间”列时:

averagetime(df["Time"])

但是当我尝试在分组后应用它时,它会给我一个错误 .

df.groupby('User')['Time'].apply(averagetime)

有什么建议我可以解决上述问题吗?

2 回答

  • 0

    您可以使用diff,通过np.timedelta64(1,'D')转换为 float 并使用abs count sum

    print (averagetime(df["Time"]))
    12.0
    
    su = ((df["Time"].diff() / np.timedelta64(1,'D')).abs().sum())
    print (su / (len(df) - 1))
    12.0
    

    然后我将它应用于 groupby ,但是有必要的条件,因为:

    ZeroDivisionError:浮点除零

    print (df.groupby('User')['Time']
             .apply(lambda x: np.nan if len(x) == 1 
                                     else (x.diff()/np.timedelta64(1,'D')).abs().sum()/(len(x)-1)))
    
    User
    A    30.0
    B    28.0
    C     NaN
    Name: Time, dtype: float64
    
  • 1

    以@ Jezrael的答案为基础:

    如果用“频率”表示 - 每个执行操作的用户之间经过了多长时间,那么这是一种方法:

    import pandas as pd
    import numpy as np
    
    data = [
        ("10/10/2016","A"),
        ("10/10/2016","B"),
        ("09/12/2016","B"),
        ("09/12/2016","A"),
        ("08/11/2016","A"),
        ("08/11/2016","C"),
    ]
    
    # Create DataFrame base
    df = pd.DataFrame(data, columns=("Time","User"))
    
    # Convert time column to correct format for time calculations
    df["Time"] = pd.to_datetime(df["Time"], dayfirst=True)
    
    # Group the DF by min, max and count the number of instances
    grouped = (df.groupby("User").agg([np.max, np.min, np.count_nonzero])
    
               # This step is a bit messy and could be improved,
               # but we need the count as an int
               .assign(counter=lambda x: x["Time"]["count_nonzero"].astype(int))
    
               # Use apply to calculate the time between first and last, then divide by frequency
               .apply(lambda x: (x["Time"]["amax"] - x["Time"]["amin"]) / x["counter"].astype(int), axis=1)
               )
    
    # Output the DF if using an interactive prompt
    grouped
    

    输出:

    User    
    A   20 days
    B   30 days
    C   0 days
    

相关问题