{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":31254,"databundleVersionId":3103714,"sourceType":"competition"}],"dockerImageVersionId":30157,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"\n","metadata":{}},{"cell_type":"markdown","source":"# EDA\n","metadata":{}},{"cell_type":"markdown","source":"## Введение\n\nВ датасете представлены различные виды данных, которые помогают создавать хорошие рекомендации для H&M:\n\n`images` - изображения для каждого article_id\n\n`articles`  - подробная метадата для каждого article_id\n\n`customers`  - подробная метадата для каждого customer_id\n\n`transactions_train`  - покупки с деталями\n\n","metadata":{}},{"cell_type":"markdown","source":"## 1. Импорт и чтение\n","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom matplotlib import pyplot as plt\nfrom tqdm.notebook import tqdm","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:14:15.164472Z","iopub.execute_input":"2024-06-29T20:14:15.164893Z","iopub.status.idle":"2024-06-29T20:14:16.492857Z","shell.execute_reply.started":"2024-06-29T20:14:15.164771Z","shell.execute_reply":"2024-06-29T20:14:16.491879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"articles = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/articles.csv\")\ncustomers = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/customers.csv\")\ntransactions = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/transactions_train.csv\")\nsample_submission = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:14:16.494901Z","iopub.execute_input":"2024-06-29T20:14:16.495257Z","iopub.status.idle":"2024-06-29T20:15:44.469463Z","shell.execute_reply.started":"2024-06-29T20:14:16.495211Z","shell.execute_reply":"2024-06-29T20:15:44.468577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Articles (таблица с товарами) \n","metadata":{}},{"cell_type":"code","source":"articles.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:44.470874Z","iopub.execute_input":"2024-06-29T20:15:44.471218Z","iopub.status.idle":"2024-06-29T20:15:44.517602Z","shell.execute_reply.started":"2024-06-29T20:15:44.471173Z","shell.execute_reply":"2024-06-29T20:15:44.516410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Доля одежды для женщин занимает значительную часть всех платьев. Спортивная одежда имеет наименьшую долю.\n\n","metadata":{}},{"cell_type":"code","source":"f, ax = plt.subplots(figsize=(15, 7))\nax = sns.histplot(data=articles, y='index_name', color='blue')\nax.set_xlabel('count by index name')\nax.set_ylabel('index name')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:44.521030Z","iopub.execute_input":"2024-06-29T20:15:44.521371Z","iopub.status.idle":"2024-06-29T20:15:45.043526Z","shell.execute_reply.started":"2024-06-29T20:15:44.521300Z","shell.execute_reply":"2024-06-29T20:15:45.042383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Одежда, сгруппированная по индексам: самая частая одежда - футболки, особенно для женщин и детей. Следующим по числу идет аксессуары, много различных аксессуаров с низкой ценой.\n\n","metadata":{}},{"cell_type":"code","source":"f, ax = plt.subplots(figsize=(15, 7))\nax = sns.histplot(data=articles, y='garment_group_name',  hue='index_group_name', multiple=\"stack\")\nax.set_xlabel('count by garment group')\nax.set_ylabel('garment group')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:45.045275Z","iopub.execute_input":"2024-06-29T20:15:45.045664Z","iopub.status.idle":"2024-06-29T20:15:46.174251Z","shell.execute_reply.started":"2024-06-29T20:15:45.045616Z","shell.execute_reply":"2024-06-29T20:15:46.173364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Женская одежда и детская/младенческая имеют подгруппы.","metadata":{}},{"cell_type":"code","source":"articles.groupby(['index_group_name', 'index_name']).count()['article_id']","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:46.175531Z","iopub.execute_input":"2024-06-29T20:15:46.175881Z","iopub.status.idle":"2024-06-29T20:15:46.396232Z","shell.execute_reply.started":"2024-06-29T20:15:46.175828Z","shell.execute_reply":"2024-06-29T20:15:46.395375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Аксессуары действительно разнообразны, самых многочисленных: сумки, серьги и головные уборы. Однако преобладают брюки","metadata":{}},{"cell_type":"code","source":"pd.options.display.max_rows = None\narticles.groupby(['product_group_name', 'product_type_name']).count()['article_id']","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:46.397703Z","iopub.execute_input":"2024-06-29T20:15:46.398050Z","iopub.status.idle":"2024-06-29T20:15:46.618155Z","shell.execute_reply.started":"2024-06-29T20:15:46.397990Z","shell.execute_reply":"2024-06-29T20:15:46.617069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"И таблица с количеством уникальных значений в столбцах","metadata":{}},{"cell_type":"code","source":"for col in articles.columns:\n    if not 'no' in col and not 'code' in col and not 'id' in col:\n        un_n = articles[col].nunique()\n        print(f'n of unique {col}: {un_n}')","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:46.619909Z","iopub.execute_input":"2024-06-29T20:15:46.620290Z","iopub.status.idle":"2024-06-29T20:15:46.809446Z","shell.execute_reply.started":"2024-06-29T20:15:46.620238Z","shell.execute_reply":"2024-06-29T20:15:46.808421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Customers (таблица с клиентами)","metadata":{}},{"cell_type":"code","source":"pd.options.display.max_rows = 50\ncustomers.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:46.811048Z","iopub.execute_input":"2024-06-29T20:15:46.811403Z","iopub.status.idle":"2024-06-29T20:15:46.831762Z","shell.execute_reply.started":"2024-06-29T20:15:46.811354Z","shell.execute_reply":"2024-06-29T20:15:46.830550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Здесь нет дубликатов","metadata":{}},{"cell_type":"code","source":"customers.shape[0] - customers['customer_id'].nunique()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:46.835895Z","iopub.execute_input":"2024-06-29T20:15:46.836227Z","iopub.status.idle":"2024-06-29T20:15:47.626293Z","shell.execute_reply.started":"2024-06-29T20:15:46.836168Z","shell.execute_reply":"2024-06-29T20:15:47.625100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Здесь аномальное количество клиентов с одним почтовым индексом. Один из них имеет 120303, это может быть закодированный адрес nan или что-то вроде крупного дистрибуционного центра или пункта выдачи.","metadata":{}},{"cell_type":"code","source":"data_postal = customers.groupby('postal_code', as_index=False).count().sort_values('customer_id', ascending=False)\ndata_postal.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:47.627848Z","iopub.execute_input":"2024-06-29T20:15:47.628188Z","iopub.status.idle":"2024-06-29T20:15:49.893412Z","shell.execute_reply.started":"2024-06-29T20:15:47.628140Z","shell.execute_reply":"2024-06-29T20:15:49.892520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Возрасты, статусы участников клуба разные, как и идентификаторы клиентов.\n\n","metadata":{}},{"cell_type":"code","source":"customers[customers['postal_code']=='2c29ae653a9282cce4151bd87643c907644e09541abc28ae87dea0d1f6603b1c'].head(5)","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:49.894778Z","iopub.execute_input":"2024-06-29T20:15:49.895108Z","iopub.status.idle":"2024-06-29T20:15:50.201733Z","shell.execute_reply.started":"2024-06-29T20:15:49.895059Z","shell.execute_reply":"2024-06-29T20:15:50.200857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Самый распространенный возраст около 21-23 лет.\n\n","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nfrom matplotlib import pyplot as plt\nsns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(10,5))\nax = sns.histplot(data=customers, x='age', bins=50, color='blue')\nax.set_xlabel('Распределение возраста клиентов')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:50.203263Z","iopub.execute_input":"2024-06-29T20:15:50.203567Z","iopub.status.idle":"2024-06-29T20:15:50.768698Z","shell.execute_reply.started":"2024-06-29T20:15:50.203528Z","shell.execute_reply":"2024-06-29T20:15:50.767632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Статус в клубе H&M. Почти у каждого клиента есть активный статус в клубе, некоторые из них начинают активировать его (предварительно создавать). Малая часть клиентов отказалась от клуба.","metadata":{}},{"cell_type":"code","source":"sns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(10,5))\nax = sns.histplot(data=customers, x='club_member_status', color='blue')\nax.set_xlabel('Распределение статуса участника клуба')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:50.769975Z","iopub.execute_input":"2024-06-29T20:15:50.770257Z","iopub.status.idle":"2024-06-29T20:15:53.019761Z","shell.execute_reply.started":"2024-06-29T20:15:50.770221Z","shell.execute_reply":"2024-06-29T20:15:53.018594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Здесь есть три типа для NO DATA. Давайте объединим эти значения.\n","metadata":{}},{"cell_type":"code","source":"customers['fashion_news_frequency'].unique()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:53.021339Z","iopub.execute_input":"2024-06-29T20:15:53.021744Z","iopub.status.idle":"2024-06-29T20:15:53.198284Z","shell.execute_reply.started":"2024-06-29T20:15:53.021698Z","shell.execute_reply":"2024-06-29T20:15:53.197245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"customers.loc[~customers['fashion_news_frequency'].isin(['Regularly', 'Monthly']), 'fashion_news_frequency'] = 'None'\ncustomers['fashion_news_frequency'].unique()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:53.199747Z","iopub.execute_input":"2024-06-29T20:15:53.199997Z","iopub.status.idle":"2024-06-29T20:15:53.528659Z","shell.execute_reply.started":"2024-06-29T20:15:53.199965Z","shell.execute_reply":"2024-06-29T20:15:53.527727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pie_data = customers[['customer_id', 'fashion_news_frequency']].groupby('fashion_news_frequency').count()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:53.530011Z","iopub.execute_input":"2024-06-29T20:15:53.530271Z","iopub.status.idle":"2024-06-29T20:15:53.934681Z","shell.execute_reply.started":"2024-06-29T20:15:53.530236Z","shell.execute_reply":"2024-06-29T20:15:53.933914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Клиенты предпочитают не получать сообщения о текущих новостях.\n\n","metadata":{}},{"cell_type":"code","source":"sns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(10,5))\ncolors = sns.color_palette('viridis')\nax.pie(pie_data.customer_id, labels=pie_data.index, colors = colors)\nax.set_facecolor('lightgrey')\nax.set_xlabel('Распределение частоты новостей о моде')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:53.935884Z","iopub.execute_input":"2024-06-29T20:15:53.936114Z","iopub.status.idle":"2024-06-29T20:15:54.063415Z","shell.execute_reply.started":"2024-06-29T20:15:53.936084Z","shell.execute_reply":"2024-06-29T20:15:54.062189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4. Transactions (таблица с транзакциями)","metadata":{}},{"cell_type":"code","source":"transactions.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:54.064942Z","iopub.execute_input":"2024-06-29T20:15:54.065805Z","iopub.status.idle":"2024-06-29T20:15:54.082372Z","shell.execute_reply.started":"2024-06-29T20:15:54.065737Z","shell.execute_reply":"2024-06-29T20:15:54.081417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Здесь мы видим выбросы.\n\n","metadata":{}},{"cell_type":"code","source":"pd.set_option('display.float_format', '{:.4f}'.format)\ntransactions.describe()['price']","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:54.083826Z","iopub.execute_input":"2024-06-29T20:15:54.084903Z","iopub.status.idle":"2024-06-29T20:15:57.364209Z","shell.execute_reply.started":"2024-06-29T20:15:54.084853Z","shell.execute_reply":"2024-06-29T20:15:57.363010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transactions.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:57.365671Z","iopub.execute_input":"2024-06-29T20:15:57.365965Z","iopub.status.idle":"2024-06-29T20:15:57.380775Z","shell.execute_reply.started":"2024-06-29T20:15:57.365918Z","shell.execute_reply":"2024-06-29T20:15:57.379530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(10,5))\nax = sns.boxplot(data=transactions, x='price', color='blue')\nax.set_xlabel('Выбросы по цене')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:15:57.382234Z","iopub.execute_input":"2024-06-29T20:15:57.382553Z","iopub.status.idle":"2024-06-29T20:16:02.058715Z","shell.execute_reply.started":"2024-06-29T20:15:57.382518Z","shell.execute_reply":"2024-06-29T20:16:02.057643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Топ-10 клиентов по количеству транзакций","metadata":{}},{"cell_type":"code","source":"transactions_byid = transactions.groupby('customer_id').count()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:16:02.060294Z","iopub.execute_input":"2024-06-29T20:16:02.060586Z","iopub.status.idle":"2024-06-29T20:16:21.236458Z","shell.execute_reply.started":"2024-06-29T20:16:02.060551Z","shell.execute_reply":"2024-06-29T20:16:21.235380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transactions_byid.sort_values(by='price', ascending=False)['price'][:10]","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:16:21.237815Z","iopub.execute_input":"2024-06-29T20:16:21.238085Z","iopub.status.idle":"2024-06-29T20:16:21.809170Z","shell.execute_reply.started":"2024-06-29T20:16:21.238050Z","shell.execute_reply":"2024-06-29T20:16:21.808132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Однако более точным будет сравнение цен внутри групп, поскольку цены на аксессуары и брюки могут сильно различаться","metadata":{}},{"cell_type":"markdown","source":"Получим сабсет из статей и объединим его с транзакциями\n","metadata":{}},{"cell_type":"code","source":"articles_for_merge = articles[['article_id', 'prod_name', 'product_type_name', 'product_group_name', 'index_name']]","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:16:21.810772Z","iopub.execute_input":"2024-06-29T20:16:21.811036Z","iopub.status.idle":"2024-06-29T20:16:21.821849Z","shell.execute_reply.started":"2024-06-29T20:16:21.811002Z","shell.execute_reply":"2024-06-29T20:16:21.820836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"articles_for_merge = transactions[['customer_id', 'article_id', 'price', 't_dat']].merge(articles_for_merge, on='article_id', how='left')","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:16:21.823133Z","iopub.execute_input":"2024-06-29T20:16:21.823441Z","iopub.status.idle":"2024-06-29T20:16:35.087891Z","shell.execute_reply.started":"2024-06-29T20:16:21.823391Z","shell.execute_reply":"2024-06-29T20:16:35.086571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Здесь мы видим различия в ценах на названия групп. Цены на одежду для нижней части тела (напр брюки)/ верхней/ всего тела сильно различаются. Это может быть похоже на некоторые уникальные коллекции  Некоторые дорогостоящие товары даже относятся к группе аксессуаров.","metadata":{}},{"cell_type":"code","source":"sns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(25,18))\nax = sns.boxplot(data=articles_for_merge, x='price', y='product_group_name')\nax.set_xlabel('Выбросы по ценам', fontsize=22)\nax.set_ylabel('Названия', fontsize=22)\nax.xaxis.set_tick_params(labelsize=22)\nax.yaxis.set_tick_params(labelsize=22)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:16:35.089472Z","iopub.execute_input":"2024-06-29T20:16:35.089760Z","iopub.status.idle":"2024-06-29T20:17:09.132651Z","shell.execute_reply.started":"2024-06-29T20:16:35.089715Z","shell.execute_reply":"2024-06-29T20:17:09.131402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Затем просмотрим таблицу цен в зависимости от группы товаров \"аксессуары\" и найд причины высоких цен внутри группы.\n\nНаибольшие отклонения можно найти среди сумок, что вполне логично. Кроме того, шарфы и другие аксессуары имеют цены, резко отличающиеся от цен на остальную одежду","metadata":{}},{"cell_type":"code","source":"sns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(25,18))\n_ = articles_for_merge[articles_for_merge['product_group_name'] == 'Accessories']\nax = sns.boxplot(data=_, x='price', y='product_type_name')\nax.set_xlabel('Выбросы по ценам', fontsize=22)\nax.set_ylabel('Названия товаров', fontsize=22)\nax.xaxis.set_tick_params(labelsize=22)\nax.yaxis.set_tick_params(labelsize=22)\ndel _\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:17:09.141029Z","iopub.execute_input":"2024-06-29T20:17:09.141471Z","iopub.status.idle":"2024-06-29T20:17:40.724561Z","shell.execute_reply.started":"2024-06-29T20:17:09.141417Z","shell.execute_reply":"2024-06-29T20:17:40.723254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Индекс с самой высокой средней ценой - это женская одежда. С самой низкой - детская.","metadata":{}},{"cell_type":"code","source":"articles_index = articles_for_merge[['index_name', 'price']].groupby('index_name').mean()\nsns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(10,5))\nax = sns.barplot(x=articles_index.price, y=articles_index.index, color='blue', alpha=0.8)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:17:40.727306Z","iopub.execute_input":"2024-06-29T20:17:40.728215Z","iopub.status.idle":"2024-06-29T20:17:48.966773Z","shell.execute_reply.started":"2024-06-29T20:17:40.728155Z","shell.execute_reply":"2024-06-29T20:17:48.965508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Самая низкая средняя цена на канцелярские товары, самая высокая - на обувь.","metadata":{}},{"cell_type":"code","source":"articles_index = articles_for_merge[['product_group_name', 'price']].groupby('product_group_name').mean()\nsns.set_style(\"darkgrid\")\nf, ax = plt.subplots(figsize=(10,5))\nax = sns.barplot(x=articles_index.price, y=articles_index.index, color='blue', alpha=0.8)\nax.set_xlabel('Цена по продуктовой группе')\nax.set_ylabel('Продуктовая группа')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:17:48.968890Z","iopub.execute_input":"2024-06-29T20:17:48.969251Z","iopub.status.idle":"2024-06-29T20:17:55.296806Z","shell.execute_reply.started":"2024-06-29T20:17:48.969204Z","shell.execute_reply":"2024-06-29T20:17:55.295597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Теперь посмотрим среднее изменение цен во времени для 5 лучших товарных групп по средней цене:\n- Обувь\n- Одежда на все тело\n- Сумки\n- Одежда для нижней части тела\n- Нижнее белье/ночные сорочки","metadata":{}},{"cell_type":"code","source":"articles_for_merge['t_dat'] = pd.to_datetime(articles_for_merge['t_dat'])","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:17:55.299426Z","iopub.execute_input":"2024-06-29T20:17:55.300400Z","iopub.status.idle":"2024-06-29T20:18:06.007922Z","shell.execute_reply.started":"2024-06-29T20:17:55.300339Z","shell.execute_reply":"2024-06-29T20:18:06.006889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"product_list = ['Shoes', 'Garment Full body', 'Bags', 'Garment Lower body', 'Underwear/nightwear']\ncolors = ['blue', 'blue', 'blue', 'blue', 'blue']\nk = 0\nf, ax = plt.subplots(3, 2, figsize=(20, 15))\nfor i in range(3):\n    for j in range(2):\n        try:\n            product = product_list[k]\n            articles_for_merge_product = articles_for_merge[articles_for_merge.product_group_name == product_list[k]]\n            series_mean = articles_for_merge_product[['t_dat', 'price']].groupby(pd.Grouper(key=\"t_dat\", freq='M')).mean().fillna(0)\n            series_std = articles_for_merge_product[['t_dat', 'price']].groupby(pd.Grouper(key=\"t_dat\", freq='M')).std().fillna(0)\n            ax[i, j].plot(series_mean, linewidth=4, color=colors[k])\n            ax[i, j].fill_between(series_mean.index, (series_mean.values-2*series_std.values).ravel(), \n                             (series_mean.values+2*series_std.values).ravel(), color=colors[k], alpha=.1)\n            ax[i, j].set_title(f'Mean {product_list[k]} price in time')\n            ax[i, j].set_xlabel('month')\n            ax[i, j].set_xlabel(f'{product_list[k]}')\n            k += 1\n        except IndexError:\n            ax[i, j].set_visible(False)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:18:06.009362Z","iopub.execute_input":"2024-06-29T20:18:06.009671Z","iopub.status.idle":"2024-06-29T20:18:37.901006Z","shell.execute_reply.started":"2024-06-29T20:18:06.009631Z","shell.execute_reply":"2024-06-29T20:18:37.899857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 5. Картинки с описанием и ценой","metadata":{}},{"cell_type":"markdown","source":"Проверим последние покупки по максимальной и минимальной цене","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as mpimg","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:18:37.902854Z","iopub.execute_input":"2024-06-29T20:18:37.903258Z","iopub.status.idle":"2024-06-29T20:18:37.908791Z","shell.execute_reply.started":"2024-06-29T20:18:37.903200Z","shell.execute_reply":"2024-06-29T20:18:37.907617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"max_price_ids = transactions[transactions.t_dat==transactions.t_dat.max()].sort_values('price', ascending=False).iloc[:5][['article_id', 'price']]\nmin_price_ids = transactions[transactions.t_dat==transactions.t_dat.min()].sort_values('price', ascending=True).iloc[:5][['article_id', 'price']]","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:18:37.910257Z","iopub.execute_input":"2024-06-29T20:18:37.910597Z","iopub.status.idle":"2024-06-29T20:18:59.532984Z","shell.execute_reply.started":"2024-06-29T20:18:37.910559Z","shell.execute_reply":"2024-06-29T20:18:59.531892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Фотографии с описанием и ценой ( 5 лучших)","metadata":{}},{"cell_type":"code","source":"f, ax = plt.subplots(1, 5, figsize=(20,10))\ni = 0\nfor _, data in max_price_ids.iterrows():\n    desc = articles[articles['article_id'] == data['article_id']]['detail_desc'].iloc[0]\n    desc_list = desc.split(' ')\n    for j, elem in enumerate(desc_list):\n        if j > 0 and j % 5 == 0:\n            desc_list[j] = desc_list[j] + '\\n'\n    desc = ' '.join(desc_list)\n    img = mpimg.imread(f'../input/h-and-m-personalized-fashion-recommendations/images/0{str(data.article_id)[:2]}/0{int(data.article_id)}.jpg')\n    ax[i].imshow(img)\n    ax[i].set_title(f'price: {data.price:.2f}')\n    ax[i].set_xticks([], [])\n    ax[i].set_yticks([], [])\n    ax[i].grid(False)\n    ax[i].set_xlabel(desc, fontsize=10)\n    i += 1\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:18:59.534565Z","iopub.execute_input":"2024-06-29T20:18:59.535638Z","iopub.status.idle":"2024-06-29T20:19:01.539168Z","shell.execute_reply.started":"2024-06-29T20:18:59.535591Z","shell.execute_reply":"2024-06-29T20:19:01.538268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Фотографии с описанием и ценой ( 5 худших)","metadata":{}},{"cell_type":"code","source":"f, ax = plt.subplots(1, 5, figsize=(20,10))\ni = 0\nfor _, data in min_price_ids.iterrows():\n    desc = articles[articles['article_id'] == data['article_id']]['detail_desc'].iloc[0]\n    desc_list = desc.split(' ')\n    for j, elem in enumerate(desc_list):\n        if j > 0 and j % 4 == 0:\n            desc_list[j] = desc_list[j] + '\\n'\n    desc = ' '.join(desc_list)\n    img = mpimg.imread(f'../input/h-and-m-personalized-fashion-recommendations/images/0{str(data.article_id)[:2]}/0{int(data.article_id)}.jpg')\n    ax[i].imshow(img)\n    ax[i].set_title(f'price: {data.price:.4f}')\n    ax[i].set_xlabel(desc, fontsize=10)\n    ax[i].set_xticks([], [])\n    ax[i].set_yticks([], [])\n    ax[i].grid(False)\n    i += 1\nplt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:19:01.540650Z","iopub.execute_input":"2024-06-29T20:19:01.540933Z","iopub.status.idle":"2024-06-29T20:19:03.308532Z","shell.execute_reply.started":"2024-06-29T20:19:01.540889Z","shell.execute_reply":"2024-06-29T20:19:03.307551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# LightFM\n","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom lightfm import LightFM\nfrom lightfm.data import Dataset\nfrom joblib import Parallel, delayed\nimport os\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:00:12.481623Z","iopub.execute_input":"2024-06-29T21:00:12.482735Z","iopub.status.idle":"2024-06-29T21:00:12.489638Z","shell.execute_reply.started":"2024-06-29T21:00:12.482676Z","shell.execute_reply":"2024-06-29T21:00:12.488052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Загрузка данных\narticles = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/articles.csv\")\ncustomers = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/customers.csv\")\ntransactions = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/transactions_train.csv\")\nsample_submission = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/sample_submission.csv\")\n\n# Подготовка данных\ndataset = Dataset()\ndataset.fit(transactions['customer_id'].unique(), transactions['article_id'].unique())\n\n(interactions, weights) = dataset.build_interactions([(x[0], x[1], x[2]) for x in transactions[['customer_id', 'article_id', 'price']].values])\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:00:37.217653Z","iopub.execute_input":"2024-06-29T21:00:37.217984Z","iopub.status.idle":"2024-06-29T21:05:09.394786Z","shell.execute_reply.started":"2024-06-29T21:00:37.217948Z","shell.execute_reply":"2024-06-29T21:05:09.393114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Обучение модели\nmodel = LightFM(loss='warp')\nmodel.fit(interactions, epochs=30, num_threads=2)\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:33:01.904350Z","iopub.execute_input":"2024-06-29T20:33:01.905996Z","iopub.status.idle":"2024-06-29T20:54:44.389376Z","shell.execute_reply.started":"2024-06-29T20:33:01.905902Z","shell.execute_reply":"2024-06-29T20:54:44.388338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Функция для получения рекомендаций\ndef get_lightfm_recommendations(customer_id, model, dataset, num_recommendations=10):\n    if customer_id not in dataset.mapping()[0]:\n        return []\n    customer_index = dataset.mapping()[0][customer_id]\n    scores = model.predict(customer_index, np.arange(len(dataset.mapping()[2])))\n    top_items = np.argsort(-scores)[:num_recommendations]\n    inv_map = {v: k for k, v in dataset.mapping()[2].items()}\n    return [inv_map[i] for i in top_items if i in inv_map]\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:06:06.477086Z","iopub.execute_input":"2024-06-29T21:06:06.477443Z","iopub.status.idle":"2024-06-29T21:06:06.486478Z","shell.execute_reply.started":"2024-06-29T21:06:06.477400Z","shell.execute_reply":"2024-06-29T21:06:06.485365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Сокращение числа пользователей для предсказаний (например, 10 пользователей)\nsubset_customers = sample_submission['customer_id'].sample(n=10, random_state=42)\nsubmission_subset = sample_submission[sample_submission['customer_id'].isin(subset_customers)].copy()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:07:02.812063Z","iopub.execute_input":"2024-06-29T21:07:02.812386Z","iopub.status.idle":"2024-06-29T21:07:03.085368Z","shell.execute_reply.started":"2024-06-29T21:07:02.812351Z","shell.execute_reply":"2024-06-29T21:07:03.084096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Определение функции для получения рекомендаций для одного пользователя\ndef get_recommendations_for_user(customer_id):\n    return ' '.join(map(str, get_lightfm_recommendations(customer_id, model, dataset)))","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:07:07.392444Z","iopub.execute_input":"2024-06-29T21:07:07.392747Z","iopub.status.idle":"2024-06-29T21:07:07.398856Z","shell.execute_reply.started":"2024-06-29T21:07:07.392714Z","shell.execute_reply":"2024-06-29T21:07:07.397702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":" # Генерация рекомендаций для всех пользователей в subset\nsubmission_subset['prediction'] = submission_subset['customer_id'].apply(lambda x: ' '.join(map(str, get_lightfm_recommendations(x, model, dataset))))\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:07:38.963923Z","iopub.execute_input":"2024-06-29T21:07:38.964308Z","iopub.status.idle":"2024-06-29T21:07:39.319118Z","shell.execute_reply.started":"2024-06-29T21:07:38.964266Z","shell.execute_reply":"2024-06-29T21:07:39.317973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Сохранение в файл\nsubmission_subset.to_csv('/kaggle/working/submission_lightfm.csv', index=False)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:07:58.067890Z","iopub.execute_input":"2024-06-29T21:07:58.068253Z","iopub.status.idle":"2024-06-29T21:07:58.078114Z","shell.execute_reply.started":"2024-06-29T21:07:58.068212Z","shell.execute_reply":"2024-06-29T21:07:58.076187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Вывод списка файлов в директории /kaggle/working\nfor dirname, _, filenames in os.walk('/kaggle/working'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:08:09.894143Z","iopub.execute_input":"2024-06-29T21:08:09.894565Z","iopub.status.idle":"2024-06-29T21:08:09.902908Z","shell.execute_reply.started":"2024-06-29T21:08:09.894517Z","shell.execute_reply":"2024-06-29T21:08:09.901525Z"},"trusted":true},"execution_count":null,"outputs":[]}]}