2016-06-16 9 views
2

I次のデータフレームを持っている:計算日の時間差DATAFRAME

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は2011年8月8日に初めて取引され、2016年9月12日に再び取引されたとしましょう(約30日後)。その後、彼は2回目の取引から約29日後、10/10/2016に再度取引しました。したがって、彼の平均頻度は(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

ない正確な答えが、おそらくあなたgoogle [pairwise difference](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiohv3d5KvNAhVU0WMKHYHWCR0QFggeMAA&url=http%3A%2F%2Fstackoverflow.com%2Fquestions%2F21467429% 2Fairwise-from-pandas-dataframe&usg = AFQjCNG1vrKJgkLxfWwiCwHyDRTzG1aevA&sig2 = 1qi6JGBnoqNr7UFuT_3xPw) – hd1

+0

あなたはdd希望の出力? – jezrael

答えて

1

あなたは、diffを使うnp.timedelta64(1,'D')によりfloatに変換し、abssumとすることができます

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: float division by zero

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 
+0

私は答えを編集して、それを確認してください。 – jezrael

+0

すばらしい解決策!どうもありがとうございます! – morfara

0

@ 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