{"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-29T19:56:11.267971Z","iopub.execute_input":"2024-06-29T19:56:11.268541Z","iopub.status.idle":"2024-06-29T19:56:11.274745Z","shell.execute_reply.started":"2024-06-29T19:56:11.268501Z","shell.execute_reply":"2024-06-29T19:56:11.273829Z"},"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-29T19:56:11.276914Z","iopub.execute_input":"2024-06-29T19:56:11.277605Z","iopub.status.idle":"2024-06-29T19:57:26.292441Z","shell.execute_reply.started":"2024-06-29T19:56:11.277558Z","shell.execute_reply":"2024-06-29T19:57:26.290451Z"},"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-29T19:57:26.294568Z","iopub.execute_input":"2024-06-29T19:57:26.295266Z","iopub.status.idle":"2024-06-29T19:57:26.399264Z","shell.execute_reply.started":"2024-06-29T19:57:26.295131Z","shell.execute_reply":"2024-06-29T19:57:26.396534Z"},"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-29T19:57:26.403453Z","iopub.execute_input":"2024-06-29T19:57:26.404336Z","iopub.status.idle":"2024-06-29T19:57:27.096658Z","shell.execute_reply.started":"2024-06-29T19:57:26.404207Z","shell.execute_reply":"2024-06-29T19:57:27.095691Z"},"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-29T19:57:27.099413Z","iopub.execute_input":"2024-06-29T19:57:27.099844Z","iopub.status.idle":"2024-06-29T19:57:28.311157Z","shell.execute_reply.started":"2024-06-29T19:57:27.099795Z","shell.execute_reply":"2024-06-29T19:57:28.309946Z"},"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-29T19:57:28.312701Z","iopub.execute_input":"2024-06-29T19:57:28.313001Z","iopub.status.idle":"2024-06-29T19:57:28.483387Z","shell.execute_reply.started":"2024-06-29T19:57:28.312961Z","shell.execute_reply":"2024-06-29T19:57:28.482498Z"},"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-29T19:57:28.485386Z","iopub.execute_input":"2024-06-29T19:57:28.485996Z","iopub.status.idle":"2024-06-29T19:57:28.642122Z","shell.execute_reply.started":"2024-06-29T19:57:28.485949Z","shell.execute_reply":"2024-06-29T19:57:28.641150Z"},"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-29T19:57:28.643481Z","iopub.execute_input":"2024-06-29T19:57:28.643771Z","iopub.status.idle":"2024-06-29T19:57:28.808669Z","shell.execute_reply.started":"2024-06-29T19:57:28.643730Z","shell.execute_reply":"2024-06-29T19:57:28.807811Z"},"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-29T19:57:28.810106Z","iopub.execute_input":"2024-06-29T19:57:28.810411Z","iopub.status.idle":"2024-06-29T19:57:28.828040Z","shell.execute_reply.started":"2024-06-29T19:57:28.810368Z","shell.execute_reply":"2024-06-29T19:57:28.827125Z"},"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-29T19:57:28.829434Z","iopub.execute_input":"2024-06-29T19:57:28.829704Z","iopub.status.idle":"2024-06-29T19:57:29.606055Z","shell.execute_reply.started":"2024-06-29T19:57:28.829668Z","shell.execute_reply":"2024-06-29T19:57:29.605158Z"},"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-29T19:57:29.607444Z","iopub.execute_input":"2024-06-29T19:57:29.607756Z","iopub.status.idle":"2024-06-29T19:57:31.204798Z","shell.execute_reply.started":"2024-06-29T19:57:29.607711Z","shell.execute_reply":"2024-06-29T19:57:31.203802Z"},"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-29T19:57:31.206260Z","iopub.execute_input":"2024-06-29T19:57:31.206657Z","iopub.status.idle":"2024-06-29T19:57:31.380706Z","shell.execute_reply.started":"2024-06-29T19:57:31.206607Z","shell.execute_reply":"2024-06-29T19:57:31.379871Z"},"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-29T19:57:31.381801Z","iopub.execute_input":"2024-06-29T19:57:31.382025Z","iopub.status.idle":"2024-06-29T19:57:31.885998Z","shell.execute_reply.started":"2024-06-29T19:57:31.381995Z","shell.execute_reply":"2024-06-29T19:57:31.885253Z"},"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-29T19:57:31.889739Z","iopub.execute_input":"2024-06-29T19:57:31.889995Z","iopub.status.idle":"2024-06-29T19:57:33.091324Z","shell.execute_reply.started":"2024-06-29T19:57:31.889956Z","shell.execute_reply":"2024-06-29T19:57:33.090610Z"},"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-29T19:57:33.092399Z","iopub.execute_input":"2024-06-29T19:57:33.092621Z","iopub.status.idle":"2024-06-29T19:57:33.184889Z","shell.execute_reply.started":"2024-06-29T19:57:33.092594Z","shell.execute_reply":"2024-06-29T19:57:33.183861Z"},"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-29T19:57:33.186699Z","iopub.execute_input":"2024-06-29T19:57:33.187260Z","iopub.status.idle":"2024-06-29T19:57:33.423221Z","shell.execute_reply.started":"2024-06-29T19:57:33.187223Z","shell.execute_reply":"2024-06-29T19:57:33.422389Z"},"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-29T19:57:33.424313Z","iopub.execute_input":"2024-06-29T19:57:33.424557Z","iopub.status.idle":"2024-06-29T19:57:33.724982Z","shell.execute_reply.started":"2024-06-29T19:57:33.424526Z","shell.execute_reply":"2024-06-29T19:57:33.724157Z"},"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-29T19:57:33.726383Z","iopub.execute_input":"2024-06-29T19:57:33.726654Z","iopub.status.idle":"2024-06-29T19:57:34.188159Z","shell.execute_reply.started":"2024-06-29T19:57:33.726621Z","shell.execute_reply":"2024-06-29T19:57:34.187280Z"},"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-29T19:57:34.189569Z","iopub.execute_input":"2024-06-29T19:57:34.190268Z","iopub.status.idle":"2024-06-29T19:57:34.204153Z","shell.execute_reply.started":"2024-06-29T19:57:34.190221Z","shell.execute_reply":"2024-06-29T19:57:34.203248Z"},"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-29T19:57:34.205629Z","iopub.execute_input":"2024-06-29T19:57:34.206572Z","iopub.status.idle":"2024-06-29T19:57:37.512296Z","shell.execute_reply.started":"2024-06-29T19:57:34.206525Z","shell.execute_reply":"2024-06-29T19:57:37.511478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transactions.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-29T19:57:37.513889Z","iopub.execute_input":"2024-06-29T19:57:37.514663Z","iopub.status.idle":"2024-06-29T19:57:37.528368Z","shell.execute_reply.started":"2024-06-29T19:57:37.514616Z","shell.execute_reply":"2024-06-29T19:57:37.527372Z"},"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-29T19:57:37.529941Z","iopub.execute_input":"2024-06-29T19:57:37.530178Z","iopub.status.idle":"2024-06-29T19:57:41.944467Z","shell.execute_reply.started":"2024-06-29T19:57:37.530129Z","shell.execute_reply":"2024-06-29T19:57:41.943592Z"},"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-29T19:57:41.945617Z","iopub.execute_input":"2024-06-29T19:57:41.945845Z","iopub.status.idle":"2024-06-29T19:57:57.425552Z","shell.execute_reply.started":"2024-06-29T19:57:41.945815Z","shell.execute_reply":"2024-06-29T19:57:57.424620Z"},"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-29T19:57:57.426761Z","iopub.execute_input":"2024-06-29T19:57:57.426998Z","iopub.status.idle":"2024-06-29T19:57:57.873482Z","shell.execute_reply.started":"2024-06-29T19:57:57.426967Z","shell.execute_reply":"2024-06-29T19:57:57.872689Z"},"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-29T19:57:57.874789Z","iopub.execute_input":"2024-06-29T19:57:57.875093Z","iopub.status.idle":"2024-06-29T19:58:01.523903Z","shell.execute_reply.started":"2024-06-29T19:57:57.875052Z","shell.execute_reply":"2024-06-29T19:58:01.523164Z"},"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-29T19:58:01.525126Z","iopub.execute_input":"2024-06-29T19:58:01.525463Z","iopub.status.idle":"2024-06-29T19:58:14.753986Z","shell.execute_reply.started":"2024-06-29T19:58:01.525404Z","shell.execute_reply":"2024-06-29T19:58:14.752819Z"},"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-29T19:58:14.755339Z","iopub.execute_input":"2024-06-29T19:58:14.755608Z","iopub.status.idle":"2024-06-29T19:58:34.631935Z","shell.execute_reply.started":"2024-06-29T19:58:14.755576Z","shell.execute_reply":"2024-06-29T19:58:34.629659Z"},"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-29T19:58:34.633627Z","iopub.execute_input":"2024-06-29T19:58:34.633922Z","iopub.status.idle":"2024-06-29T19:58:46.866857Z","shell.execute_reply.started":"2024-06-29T19:58:34.633885Z","shell.execute_reply":"2024-06-29T19:58:46.865081Z"},"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-29T19:58:46.868062Z","iopub.execute_input":"2024-06-29T19:58:46.868297Z","iopub.status.idle":"2024-06-29T19:58:51.432292Z","shell.execute_reply.started":"2024-06-29T19:58:46.868259Z","shell.execute_reply":"2024-06-29T19:58:51.431338Z"},"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-29T19:58:51.434041Z","iopub.execute_input":"2024-06-29T19:58:51.434353Z","iopub.status.idle":"2024-06-29T19:58:56.108993Z","shell.execute_reply.started":"2024-06-29T19:58:51.434310Z","shell.execute_reply":"2024-06-29T19:58:56.108041Z"},"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-29T19:58:56.110144Z","iopub.execute_input":"2024-06-29T19:58:56.110375Z","iopub.status.idle":"2024-06-29T19:59:03.675828Z","shell.execute_reply.started":"2024-06-29T19:58:56.110346Z","shell.execute_reply":"2024-06-29T19:59:03.675044Z"},"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-29T19:59:03.677539Z","iopub.execute_input":"2024-06-29T19:59:03.677848Z","iopub.status.idle":"2024-06-29T19:59:19.088186Z","shell.execute_reply.started":"2024-06-29T19:59:03.677808Z","shell.execute_reply":"2024-06-29T19:59:19.087141Z"},"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-29T19:59:19.089449Z","iopub.execute_input":"2024-06-29T19:59:19.089689Z","iopub.status.idle":"2024-06-29T19:59:19.094076Z","shell.execute_reply.started":"2024-06-29T19:59:19.089659Z","shell.execute_reply":"2024-06-29T19:59:19.093316Z"},"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-29T19:59:19.095603Z","iopub.execute_input":"2024-06-29T19:59:19.095813Z","iopub.status.idle":"2024-06-29T19:59:28.090317Z","shell.execute_reply.started":"2024-06-29T19:59:19.095787Z","shell.execute_reply":"2024-06-29T19:59:28.089391Z"},"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-29T19:59:28.091551Z","iopub.execute_input":"2024-06-29T19:59:28.091782Z","iopub.status.idle":"2024-06-29T19:59:29.724180Z","shell.execute_reply.started":"2024-06-29T19:59:28.091752Z","shell.execute_reply":"2024-06-29T19:59:29.723246Z"},"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-29T19:59:29.725592Z","iopub.execute_input":"2024-06-29T19:59:29.726529Z","iopub.status.idle":"2024-06-29T19:59:31.419060Z","shell.execute_reply.started":"2024-06-29T19:59:29.726481Z","shell.execute_reply":"2024-06-29T19:59:31.417512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Implicit\n","metadata":{}},{"cell_type":"code","source":"from implicit.als import AlternatingLeastSquares\nfrom scipy.sparse import coo_matrix\n\n# Преобразование идентификаторов в числовые индексы\ncustomer_id_map = {id: index for index, id in enumerate(customers['customer_id'].unique())}\narticle_id_map = {id: index for index, id in enumerate(articles['article_id'].unique())}\n\ntransactions['customer_index'] = transactions['customer_id'].map(customer_id_map)\ntransactions['article_index'] = transactions['article_id'].map(article_id_map)\n\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:19:01.580834Z","iopub.execute_input":"2024-06-29T20:19:01.581108Z","iopub.status.idle":"2024-06-29T20:19:11.751004Z","shell.execute_reply.started":"2024-06-29T20:19:01.581069Z","shell.execute_reply":"2024-06-29T20:19:11.750046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Создание разреженной матрицы взаимодействий\nuser_item_matrix = coo_matrix(\n    (transactions['price'].astype(float), \n     (transactions['customer_index'], transactions['article_index']))\n)","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:21:09.008282Z","iopub.execute_input":"2024-06-29T20:21:09.009030Z","iopub.status.idle":"2024-06-29T20:21:09.450801Z","shell.execute_reply.started":"2024-06-29T20:21:09.008983Z","shell.execute_reply":"2024-06-29T20:21:09.450063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Обучение модели ALS\nmodel = AlternatingLeastSquares(factors=50, regularization=0.01, iterations=20)\nmodel.fit(user_item_matrix.T)  # Transpose matrix for ALS\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-29T20:30:07.559075Z","iopub.execute_input":"2024-06-29T20:30:07.559796Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Функция для получения рекомендаций\ndef get_recommendations(customer_id, model, user_item_matrix, customer_id_map, article_id_map, num_recommendations=10):\n    user_index = customer_id_map[customer_id]\n    recommendations = model.recommend(user_index, user_item_matrix.tocsr(), N=num_recommendations)\n    recommended_article_indices = [rec[0] for rec in recommendations]\n    inv_article_id_map = {v: k for k, v in article_id_map.items()}\n    recommended_article_ids = [inv_article_id_map[idx] for idx in recommended_article_indices]\n    return recommended_article_ids","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:09:43.204657Z","iopub.execute_input":"2024-06-29T21:09:43.205595Z","iopub.status.idle":"2024-06-29T21:09:43.213195Z","shell.execute_reply.started":"2024-06-29T21:09:43.205543Z","shell.execute_reply":"2024-06-29T21:09:43.212323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Получение рекомендаций для конкретного пользователя\ncustomer_id = sample_submission['customer_id'].iloc[0]\nrecommendations = get_recommendations(customer_id, model, user_item_matrix, customer_id_map, article_id_map)\nprint(f\"Recommendations for customer {customer_id}: {recommendations}\")","metadata":{"execution":{"iopub.status.busy":"2024-06-29T21:09:46.843968Z","iopub.execute_input":"2024-06-29T21:09:46.844287Z","iopub.status.idle":"2024-06-29T21:09:49.124981Z","shell.execute_reply.started":"2024-06-29T21:09:46.844246Z","shell.execute_reply":"2024-06-29T21:09:49.124012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from joblib import Parallel, delayed\nimport os\n\n# Сокращение числа пользователей для предсказаний (например, 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# Определение функции для получения рекомендаций для одного пользователя\ndef get_recommendations_for_user(customer_id):\n    return ' '.join(map(str, get_recommendations(customer_id, model, user_item_matrix, customer_id_map, article_id_map)))\n\n# Генерация рекомендаций для всех пользователей в параллельных потоках (например, с использованием 4 потоков)\nsubmission_subset.loc[:, 'prediction'] = Parallel(n_jobs=4)(\n    delayed(get_recommendations_for_user)(customer_id) for customer_id in submission_subset['customer_id']\n)\n\n# Сохранение в файл\nsubmission_subset.to_csv('/kaggle/working/submission_subset.csv', index=False)\n\n# Вывод списка файлов в директории /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:09:56.040711Z","iopub.execute_input":"2024-06-29T21:09:56.041456Z","iopub.status.idle":"2024-06-29T21:12:06.291299Z","shell.execute_reply.started":"2024-06-29T21:09:56.041384Z","shell.execute_reply":"2024-06-29T21:12:06.290386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}