Панды — Подсчитайте количество покупок для каждого клиента для каждого конкретного продукта

#python #pandas #dataframe #data-science

#питон #панды #фрейм данных #наука о данных

Вопрос:

Входные данные, история транзакций в файлах JSON:

 {"customer_id": "C1", "basket": [{"product_id": "P3", "price": 506}, {"product_id": "P4", "price": 121}], "date_of_purchase": "2018-09-01 11:09:00"} {"customer_id": "C27", "basket": [{"product_id": "P57", "price": 154}, {"product_id": "P42", "price": 349}, {"product_id": "P47", "price": 180}], "date_of_purchase": "2021-09-06 04:52:08.505909"} {"customer_id": "C1", "basket": [{"product_id": "P3", "price": 506}, {"product_id": "P4", "price": 121}], "date_of_purchase": "2018-10-01 11:09:00"}  

Фрейм данных:

 customer_id basket date_of_purchase 0 C4 [{'product_id': 'P31', 'price': 26}] 2021-09-06 05:47:08.505909 1 C13 [{'product_id': 'P36', 'price': 566}] 2021-09-06 03:52:08.505909 2 C15 [{'product_id': 'P02', 'price': 839}] 2021-09-06 05:48:08.505909 3 C22 [{'product_id': 'P37', 'price': 1235}] 2021-09-05 20:52:08.505909 4 C27 [{'product_id': 'P57', 'price': 154}, {'produc... 2021-09-06 04:52:08.505909  

Мой код для считывания JSON в фрейм данных:

 def read_json_folder(json_folder: str):  transactions_files = glob.glob("{}*/*.json".format(json_folder))   return pandas.concat(pandas.read_json(tf, lines=True) for tf in transactions_files)  

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

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

 customer_id product_id purchase_count C1 P2 11 C1 P3 5  C2 P9 7  

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

1. У вас уже есть JSON в фрейме данных?

2. @user17242583 да, это уже есть в кадре данных.

3. Как ты его туда протащил? вот так? pd.json_normalize(j, record_path='basket', meta='customer_id') (где j находится список объектов json)

Ответ №1:

  1. Создайте фрейм данных из данных
    • read_json с аргументом строк
    • разнесите список корзин по строкам корзины
    • разложите информацию о продукте по идентификаторам продуктов и ценам
    • отбросьте ненужные столбцы
  2. Построить результирующий кадр данных из df
    • группбай и граф
    • переименуйте столбец «количество»
 gt;gt;gt;TESTDATA=""" ...{"customer_id": "C1", "basket": [{"product_id": "P3", "price": 506}, {"product_id": "P4", "price": 121}], "date_of_purchase": "2018-09-01 11:09:00"} ...{"customer_id": "C27", "basket": [{"product_id": "P57", "price": 154}, {"product_id": "P42", "price": 349}, {"product_id": "P47", "price": 180}], "date_of_purchase": "2021-09-06 04:52:08.505909"} ...{"customer_id": "C1", "basket": [{"product_id": "P3", "price": 506}, {"product_id": "P4", "price": 121}], "date_of_purchase": "2018-10-01 11:09:00"} ...""" gt;gt;gt;df = pd.read_json(TESTDATA, lines=True) gt;gt;gt;df = df.explode('basket') gt;gt;gt;df[['product_id', 'price']] = df['basket'].apply(pd.Series) gt;gt;gt;df.drop(['basket', 'price'], axis=1, inplace=True) gt;gt;gt;df2 = df.groupby(['customer_id', 'product_id'], as_index=False).count() gt;gt;gt;df2.rename(columns={'date_of_purchase': 'purchase_count'}, inplace=True) gt;gt;gt;df2  customer_id product_id purchase_count 0 C1 P3 2 1 C1 P4 2 2 C27 P42 1 3 C27 P47 1 4 C27 P57 1  

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

1. третий столбец должен быть purchase_count, а не date_of_purchase

2. @Casper2210 , я добавил строку для переименования

Ответ №2:

Если ваш фрейм данных будет таким:

 shop_list = [ {"customer_id": "C1", "basket": [{"product_id": "P3", "price": 506}, {"product_id": "P4", "price": 121}], "date_of_purchase": "2018-09-01 11:09:00"}, {"customer_id": "C27", "basket": [{"product_id": "P57", "price": 154}, {"product_id": "P42", "price": 349}, {"product_id": "P47", "price": 180}], "date_of_purchase": "2021-09-06 04:52:08.505909"}, {"customer_id": "C1", "basket": [{"product_id": "P3", "price": 506}, {"product_id": "P4", "price": 121}], "date_of_purchase": "2018-10-01 11:09:00"} ]  shop = pd.DataFrame(shop_list)   

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

 customer_groupby = shop.groupby('customer_id')['basket'].apply(list).to_dict() for k in customer_groupby.keys():  customer_groupby[k] = [item['product_id'] for sublist in customer_groupby[k] for item in sublist]  output:  #{'C1': ['P3', 'P4', 'P3', 'P4'], 'C27': ['P57', 'P42', 'P47']}   

затем создайте таблицу результатов:

 table= pd.DataFrame(columns=['customer_id', 'product_id', 'purchase_count']) for customer,value in customer_groupby.items():  items = set(value)  for item in items:  table= table.append({'customer_id':customer, 'product_id':item, 'purchase_count':value.count(item)}, ignore_index=True)  

конечный результат:

введите описание изображения здесь

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

1. Отвечает ли это решение на ваш вопрос?@ Каспер2210

Ответ №3:

Попробуйте это:

 purchase_counts = df.groupby(['customer_id', 'product_id'], as_index=False).count()  

Выход:

 gt;gt;gt; purchase_counts  customer_id product_id price 0 C1 P3 2 1 C1 P4 2 2 C27 P42 1 3 C27 P47 1 4 C27 P57 1  

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

1. Если мой код не работает для вас, не могли бы вы добавить пример того, как выглядит ваш фрейм данных, к вопросу?