#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
повлияет на производительность при увеличении размера. Люди здесь хотят дать наилучший ответ, который они могут. Я пытаюсь сделать то же самое.