2016-06-16 3 views
2

У меня есть следующий dataframe:Вычислить время различия дня в панде 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') 

Каждая строка представляет, когда пользователь делает определенное действие. Я хочу рассчитать, как часто (с точки зрения дней) каждый пользователь делает это конкретное действие.

Предположим, что пользователь впервые совершил транзакцию в первый раз 08/11/2016, после чего он снова совершил повторное депонирование 09/12/2016, то есть примерно через 30 дней после этого. Затем он снова сдал 10/10/2016, примерно через 29 дней после его второй транзакции. Таким образом, его средняя частота в днях была бы (29 + 30)/2.

Каков наиболее эффективный способ сделать это?

Заранее благодарен!


  • Update

я написал следующую функцию, которая вычисляет мой желаемый результат.

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

Не точный ответ, но, возможно, вы будет пытаться выполнить поиск в googling [попарно] (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% 2Fpairwise-matrix-from-a-pandas-dataframe & usg = AFQjCNG1vrKJgkLxfWwiCwHyDRTzG1aevA & sig2 = 1qi6JGBnoqNr7UFuT_3xPw) – hd1

+0

Можете ли вы dd желаемый выход? – jezrael

ответ

1

Вы можете использовать diff, конвертировать в float по np.timedelta64(1,'D') и 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: 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 
Смежные вопросы