我有以下数据框:
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')
每行代表用户进行特定操作的时间。我想计算每个用户执行该特定操作的频率(以天为单位)。
假设用户A在2016年11月8日第一次交易,然后他在2016年12月9日再次交易,即大约30天后交易。然后,他在2016年10月10日,也就是他第二次交易后大约29天再次交易。因此,他的平均频率为(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)
有什么建议我可以解决上述问题吗?
答案 0 :(得分:1)
您可以使用diff
,按np.timedelta64(1,'D')
转换为float
,abs
转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 :(得分:0)
以@ Jezrael的回答为基础:
如果通过&#34;多久&#34;你的意思是 - 每个执行动作的用户之间经过了多长时间,然后这是一种方法:
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