#python #pandas #dataframe #bigdata
Вопрос:
У меня есть следующий набор данных:
CustomerID Date Amount Department
0 395134 2019-01-01 199 Home
1 395134 2019-01-01 279 Home
2 1356012 2019-01-07 279 Home
3 1921374 2019-01-08 269 Home
4 395134 2019-01-01 279 Home
... ... ... ... ...
18926474 1667426 2021-06-30 349 Womenswear
18926475 1667426 2021-06-30 299 Womenswear
18926476 583105 2021-06-30 349 Womenswear
18926477 538137 2021-06-30 279 Womenswear
18926478 825382 2021-06-30 2499 Home
DaysSincePurchase
0 986 days
1 986 days
2 980 days
3 979 days
4 986 days
... ...
18926474 75 days
18926475 75 days
18926476 75 days
18926477 75 days
18926478 75 days
Я хочу заняться разработкой некоторых функций и добавить несколько столбцов после агрегирования (с помощью group_by) по идентификатору клиента. Столбец Даты не имеет значения и может быть легко удален. Мне нужен набор данных, в котором каждая строка представляет собой один уникальный идентификатор пользователя, который является просто целыми числами 1,2… (первый столбец), где остальные столбцы:
- Общая сумма покупки
- Дней с момента последней покупки
- Общее количество отделов
Это то, что я сделал, и это работает. Однако, когда я засекаю время, это занимает около 1,5 часов. Есть ли другой более эффективный способ сделать это?
customer_group = joinedData.groupby(['CustomerID'])
n = originalData['CustomerID'].nunique()
# First arrange the data in a matrix.
matrix = np.zeros((n,5)) # Pre-allocate matrix
for i in range(0,n):
matrix[i,0] = i 1
matrix[i,1] = sum(customer_group.get_group(i 1)['Amount'])
matrix[i,2] = min(customer_group.get_group(i 1)['DaysSincePurchase']).days
matrix[i,3] = customer_group.get_group(i 1)['Department'].nunique()
# The above loop takes 6300 sec approx
# convert matrix to dataframe and name columns
newData = pd.DataFrame(matrix)
newData = newData.rename(columns = {0:"CustomerID"})
newData = newData.rename(columns = {1:"TotalDemand"})
newData = newData.rename(columns = {2:"DaysSinceLastPurchase"})
newData = newData.rename(columns = {3:"nrDepartments"})
Комментарии:
1. Не могли бы вы поделиться набором данных?
2. @Люк, я поместил его фотографию в пост, разве тебе это не видно? Или вы имеете в виду загрузку всего набора данных? К сожалению, я не могу его загрузить.
3. Если бы вы могли предоставить весь набор данных, сообщество SO смогло бы разработать подход и сравнить его производительность с вашей, иначе этот вопрос был бы довольно бессмысленным
4. @Luke — я полностью понимаю и хотел бы понять. Но такой обмен файлами данных противоречит политике компании :/
Ответ №1:
Воспользуйся agg
:
>>> df.groupby('CustomerID').agg(TotalDemand=('Amount', sum),
DaysSinceLastPurchase=('DaysSincePurchase', min),
nrDepartments=('Department', 'nunique'))
Я запустил эту функцию над фреймом данных из 20 000 000 записей. Это заняло несколько секунд, чтобы быть выполненным:
>>> %timeit df.groupby('CustomerID').agg(...)
14.7 s ± 225 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Сгенерированные данные:
N = 20000000
df = pd.DataFrame(
{'CustomerID': np.random.randint(1000, 10000, N),
'Date': np.random.choice(pd.date_range('2020-01-01', '2020-12-31'), N),
'Amount': np.random.randint(100, 1000, N),
'Department': np.random.choice(['Home', 'Sport', 'Food', 'Womenswear',
'Menswear', 'Furniture'], N)})
df['DaysSincePurchase'] = pd.Timestamp.today().normalize() - df['Date']