сгруппируйте pandas по столбцу, затем получите среднее количество дней из столбца даты для каждой группы

#python #python-3.x #pandas #dataframe #data-analysis

#python #python-3.x #панды #фрейм данных #анализ данных

Вопрос:

У меня есть имя данных pandas, подобное этому:

     customer_id    transaction_date   ......................
 0    12341          2011-05-06
 1    12341          2011-06-22
 2    12341          2011-05-09
 3    12342          2011-06-16
 4    12342          2011-07-26
 5    12342          2011-03-06
 6    12343          2011-05-16
 7    12343          2011-04-25
 8    12342          2011-07-12
 9    12343          2011-05-09
 10   12343          2011-04-12
 11   12342          2011-07-03
 

Я пытаюсь рассчитать средний интервал, с которым клиент совершает транзакции. Другими словами, каждое какое количество дней каждый клиент совершает транзакцию.

Вот что я пробовал:

 dummy_data.groupby(by=['customer_id'])['transaction_date'].transform('mean')
 

Я получаю:

 DataError: No numeric types to aggregate
 

Как мне это сделать?

РЕДАКТИРОВАТЬ 1:

Ожидаемый результат:

 customer_id   avg_days
  12341         24
  12342         ..
  12343         ..
 

Объяснение:
для клиента с идентификатором «12341» дата первой транзакции — 6 мая, следующей-9 мая, следующей — 22 июня. Таким образом, разница в днях между первыми двумя транзакциями составляет 3 дня, а между следующей транзакцией — 45 дней. Итак, среднее значение для 3 и 45 равно (45 3/2 = 48/2 = 24). Затем мне нужно было бы сделать это для всех клиентов в фрейме данных.

Комментарии:

1. это строка, а не целочисленный столбец. вы принимаете во внимание даты, поэтому получаете эту ошибку

2. это в правильном формате: datetime64[ns] и да, это не числовой столбец. итак, как мне рассчитать среднее количество дней без ошибок?

3. Можете ли вы, по крайней мере, дать нам ожидаемый результат? Я не понял, что вы подразумеваете под средней датой?

4. Я добавил ожидаемый результат.

5. Проверьте мой обновленный ответ.

Ответ №1:

Сначала преобразуйте transaction_date столбец в pandas datetime , используя pd.to_datetime

 In [2947]: df.transaction_date = pd.to_datetime(df.transaction_date)
 

Теперь добавьте новый столбец df с разницей в днях между двумя транскрипциями, используя Groupby.shift и найдите среднее значение, используя Groupby.mean :

 In [2976]: df['days'] = (df.sort_values('transaction_date').groupby('customer_id').transaction_date.shift() - df.transaction_date).dt.days.abs()

In [2985]: x = df.groupby('customer_id', as_index=False)['days'].mean().round()

In [2986]: x
Out[2986]: 
   customer_id  days
0        12341  24.0
1        12342  36.0
2        12343  11.0
 

Ответ №2:

Учитывая ваш df:

 def AVG_diff(x):
    # Integer number of Days
    return x.diff().mean()

df = df.sort_values(['customer_id', 'transaction_date'], ascending=[True, True]).reset_index(drop=True)
df['transaction_date'] = pd.to_datetime(df['transaction_date'])
df.groupby('customer_id')['transaction_date'].apply(lambda x: AVG_diff(x)).reset_index()
 

Результат:

    customer_id transaction_date
0        12341 23 days 12:00:00
1        12342 35 days 12:00:00
2        12343 11 days 08:00:00
 

Обновить:

 x = df.groupby('customer_id')['transaction_date']
aggs = df.assign(avg_num=x.diff().dt.days) 
               .groupby(['customer_id'], as_index=False)['avg_num'].mean().round()
 

aggs:

    customer_id  avg_num
0        12341     24.0
1        12342     36.0
2        12343     11.0
 

Комментарии:

1. apply в основном это циклы под капотом. Так что это медленно. Пожалуйста, проверьте мое решение.

2. Да, apply работает медленнее, но если размер данных не слишком велик, тогда его можно использовать.

3. Я никогда не говорил, что его нельзя использовать apply . Просто указал на это, что apply повлияет на производительность при увеличении размера. Люди здесь хотят дать наилучший ответ, который они могут. Я пытаюсь сделать то же самое.