{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \n\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-02T06:18:34.986094Z","iopub.execute_input":"2022-03-02T06:18:34.986413Z","iopub.status.idle":"2022-03-02T06:18:36.012393Z","shell.execute_reply.started":"2022-03-02T06:18:34.986328Z","shell.execute_reply":"2022-03-02T06:18:36.011651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Preprocessing\n### Articles","metadata":{}},{"cell_type":"code","source":"# read data\ndf_articles = pd.read_csv(\"/kaggle/input/h-and-m-personalized-fashion-recommendations/articles.csv\")\n# drop duplicates\ndf_articles.drop_duplicates(inplace=True)\n# reduce memory usage\ndf_articles['article_id'] = df_articles['article_id'].astype('int32')\n# display a few rows\ndisplay(df_articles.head())\nprint()\n# display information\ndisplay(df_articles.info())\nprint()\n# missing information %\nprint(\"Missing values (%):\")\nprint(df_articles.isna().sum() * 100 / len(df_articles))","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:18:36.013806Z","iopub.execute_input":"2022-03-02T06:18:36.013997Z","iopub.status.idle":"2022-03-02T06:18:37.433435Z","shell.execute_reply.started":"2022-03-02T06:18:36.013974Z","shell.execute_reply":"2022-03-02T06:18:37.432537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for col in df_articles.columns:\n    print(col, \":\")\n    print(\" \", df_articles[col].nunique(), \"distinct values\")","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:18:37.434782Z","iopub.execute_input":"2022-03-02T06:18:37.435085Z","iopub.status.idle":"2022-03-02T06:18:37.580816Z","shell.execute_reply.started":"2022-03-02T06:18:37.435044Z","shell.execute_reply":"2022-03-02T06:18:37.579766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Customers","metadata":{}},{"cell_type":"code","source":"# read data\ndf_customers = pd.read_csv(\"/kaggle/input/h-and-m-personalized-fashion-recommendations/customers.csv\")\n# drop duplicates\ndf_customers.drop_duplicates(inplace=True)\n# reduce memory usage\ndf_customers['customer_id'] =\\\n    df_customers['customer_id'].apply(lambda x: int(x[-16:],16) ).astype('int64')\n# display a few rows\ndisplay(df_customers.head())\nprint()\n# display information\ndisplay(df_customers.info())\nprint()\n# missing information %\nprint(\"Missing values (%):\")\nprint(df_customers.isna().sum() * 100 / len(df_customers))","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:18:37.583936Z","iopub.execute_input":"2022-03-02T06:18:37.584172Z","iopub.status.idle":"2022-03-02T06:18:45.988195Z","shell.execute_reply.started":"2022-03-02T06:18:37.584145Z","shell.execute_reply":"2022-03-02T06:18:45.987277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Transactions","metadata":{}},{"cell_type":"code","source":"# read data\ndf_transactions = pd.read_csv(\"/kaggle/input/h-and-m-personalized-fashion-recommendations/transactions_train.csv\")\n# reduce memory usage\ndf_transactions['article_id'] = df_transactions['article_id'].astype('int32')\ndf_transactions['customer_id'] =\\\n    df_transactions['customer_id'].apply(lambda x: int(x[-16:],16) ).astype('int64')\n# handle the date column\ndf_transactions.t_dat = pd.to_datetime(df_transactions.t_dat)\ndf_transactions['year'] = (df_transactions.t_dat.dt.year-2000).astype('int8')\ndf_transactions['month'] = (df_transactions.t_dat.dt.month).astype('int8')\ndf_transactions['day'] = (df_transactions.t_dat.dt.day).astype('int8')\n#del df_transactions['t_dat']\n# display a few rows\ndisplay(df_transactions)\nprint()\n# display information\ndisplay(df_transactions.info())\nprint()\n# missing information %\nprint(\"Missing values (%):\")\nprint(df_transactions.isna().sum() * 100 / len(df_transactions))","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:18:45.989632Z","iopub.execute_input":"2022-03-02T06:18:45.989954Z","iopub.status.idle":"2022-03-02T06:20:22.615541Z","shell.execute_reply.started":"2022-03-02T06:18:45.989912Z","shell.execute_reply":"2022-03-02T06:20:22.614568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The transaction data from period **20 Sept 2018** till **22 Sept 2020** were given.\nSelect full year data in **2019** for analysis.","metadata":{}},{"cell_type":"code","source":"df_transactions = df_transactions[df_transactions['year']==19]","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:22.616785Z","iopub.execute_input":"2022-03-02T06:20:22.618837Z","iopub.status.idle":"2022-03-02T06:20:23.836288Z","shell.execute_reply.started":"2022-03-02T06:20:22.618797Z","shell.execute_reply":"2022-03-02T06:20:23.835338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Analysis\n### Which articles are the bestsellers?","metadata":{}},{"cell_type":"code","source":"bestsellers_ranking = df_transactions.groupby('article_id').count().sort_values(by='customer_id', ascending=False)\nbestsellers_ranking.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:23.837542Z","iopub.execute_input":"2022-03-02T06:20:23.837827Z","iopub.status.idle":"2022-03-02T06:20:24.821750Z","shell.execute_reply.started":"2022-03-02T06:20:23.837796Z","shell.execute_reply":"2022-03-02T06:20:24.821020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The top bestseller article has an average sales of 29869/365 ~= 82 units per day. The bestseller ranked number five has an average sales of 12869/365 ~= 35 units per day, which is less than half of the sales of the top bestseller.","metadata":{"execution":{"iopub.status.busy":"2022-02-26T09:45:37.63635Z","iopub.execute_input":"2022-02-26T09:45:37.636642Z","iopub.status.idle":"2022-02-26T09:45:37.64287Z","shell.execute_reply.started":"2022-02-26T09:45:37.636613Z","shell.execute_reply":"2022-02-26T09:45:37.642254Z"}}},{"cell_type":"code","source":"# add 2019 sales data to df_articles\narticle_sales = df_transactions.groupby('article_id').count()\ndef f(x):\n    try:\n        return article_sales.loc[x]['customer_id']\n    except:\n        return 0\ndf_articles['total_sales_2019'] = df_articles['article_id'].apply(f)\ndf_articles","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:24.822924Z","iopub.execute_input":"2022-03-02T06:20:24.823146Z","iopub.status.idle":"2022-03-02T06:20:32.169125Z","shell.execute_reply.started":"2022-03-02T06:20:24.823120Z","shell.execute_reply":"2022-03-02T06:20:32.168154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"to_drop = ['product_type_no',\n 'graphical_appearance_no',\n 'colour_group_code',\n 'perceived_colour_value_id',\n 'perceived_colour_master_id',\n 'department_no',\n 'index_code',\n 'index_group_no',\n 'section_no',\n 'garment_group_no']\ndf_articles.drop(columns=to_drop, axis=1, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:32.170230Z","iopub.execute_input":"2022-03-02T06:20:32.170436Z","iopub.status.idle":"2022-03-02T06:20:32.192541Z","shell.execute_reply.started":"2022-03-02T06:20:32.170411Z","shell.execute_reply":"2022-03-02T06:20:32.191831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_articles.sort_values(by='total_sales_2019', ascending=False).head(10)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:32.195667Z","iopub.execute_input":"2022-03-02T06:20:32.196058Z","iopub.status.idle":"2022-03-02T06:20:32.247087Z","shell.execute_reply.started":"2022-03-02T06:20:32.196013Z","shell.execute_reply":"2022-03-02T06:20:32.246502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The top two bestsellers are denim `Trousers`, with black colour having more sales than light blue. 8 out of the top 10 topsellers are `Black`. \n\nFrom before, there are 105542 distinct `article_id` in the articles dataset. Hence we define the **top 1000** (~1%) articles with most sales as a **bestseller**. ","metadata":{}},{"cell_type":"code","source":"bestsellers = df_articles.sort_values(by='total_sales_2019', ascending=False).head(1000)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:32.248264Z","iopub.execute_input":"2022-03-02T06:20:32.248683Z","iopub.status.idle":"2022-03-02T06:20:32.283510Z","shell.execute_reply.started":"2022-03-02T06:20:32.248654Z","shell.execute_reply":"2022-03-02T06:20:32.282896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15,5))\ng = sns.countplot(x=\"colour_group_name\", #Show count of observations\n                  data=bestsellers,\n                  palette=\"pastel\")\ng.bar_label(g.containers[0])\ng.tick_params(axis='x', rotation=90)\nplt.title('Color Group of Bestsellers on H&M')\nplt.show(g)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:32.284846Z","iopub.execute_input":"2022-03-02T06:20:32.285046Z","iopub.status.idle":"2022-03-02T06:20:32.806733Z","shell.execute_reply.started":"2022-03-02T06:20:32.285023Z","shell.execute_reply":"2022-03-02T06:20:32.805919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"`Black` is indeed the most popular colour.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(15,5))\ng = sns.countplot(x=\"garment_group_name\", #Show count of observations\n                  #data=df_articles[df_articles['total_sales_2019'] >= 8000],\n                  data=df_articles,\n                  palette=\"pastel\")\ng.bar_label(g.containers[0])\ng.tick_params(axis='x', rotation=90)\nplt.title('All Articles on H&M')\nplt.show(g)\nplt.figure(figsize=(15,5))\nh = sns.countplot(x=\"garment_group_name\", #Show count of observations\n                  data=bestsellers,\n                  #data=df_articles,\n                  palette=\"pastel\")\nh.bar_label(h.containers[0])\nh.tick_params(axis='x', rotation=90)\nplt.title('Bestselling Articles on H&M')\nplt.show(h)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:32.807917Z","iopub.execute_input":"2022-03-02T06:20:32.808159Z","iopub.status.idle":"2022-03-02T06:20:33.616841Z","shell.execute_reply.started":"2022-03-02T06:20:32.808131Z","shell.execute_reply":"2022-03-02T06:20:33.615855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"H&M sells a lot of types of `Jersey Fancy` articles, but the top three bestsellers are still mostly `Swimwear`, `Jersey Basic`, and `Trousers`. Besides that, `Accesories` is the number two among all articles, but does not constitute much of the bestsellers.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(8,5))\ng = sns.countplot(x=\"index_group_name\", \n                  data=df_articles,\n                  palette=\"pastel\")\ng.bar_label(g.containers[0])\ng.tick_params(axis='x', rotation=90)\nplt.title('All Articles on H&M')\nplt.show(g)\nplt.figure(figsize=(8,5))\ng = sns.countplot(x=\"index_group_name\", \n                  data=bestsellers,\n                  palette=\"pastel\")\ng.bar_label(g.containers[0])\ng.tick_params(axis='x', rotation=90)\nplt.title('Bestselling Articles on H&M')\nplt.show(g)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:33.618727Z","iopub.execute_input":"2022-03-02T06:20:33.618948Z","iopub.status.idle":"2022-03-02T06:20:34.084378Z","shell.execute_reply.started":"2022-03-02T06:20:33.618923Z","shell.execute_reply":"2022-03-02T06:20:34.083689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A quick look at the Divided Collection on the official H&M website shows that it is targeted towards feminine styles. We can see that most bestselling articles were designed for the female demographic. It is inferred that most customers that contribute to the sales of H&M articles belong to the female demographic. Besides that, although H&M produces a lot of Baby/Children articles, none of them made it to the bestsellers.","metadata":{}},{"cell_type":"markdown","source":"### Who contributes to the bestsellers? \nLet's see if there is a certain age group that contributes mostly to the sales of the bestselling articles.","metadata":{}},{"cell_type":"code","source":"bestsellers_transactions = df_transactions[df_transactions['article_id'].isin(bestsellers['article_id'])]\nbestsellers_contributors = df_customers[df_customers['customer_id'].isin(bestsellers_transactions['customer_id'])]\nbestsellers_contributors.head()","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:34.085572Z","iopub.execute_input":"2022-03-02T06:20:34.085841Z","iopub.status.idle":"2022-03-02T06:20:34.814022Z","shell.execute_reply.started":"2022-03-02T06:20:34.085810Z","shell.execute_reply":"2022-03-02T06:20:34.813145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# age of customers\ng = sns.histplot(df_customers['age'], #Plot univariate distribution\n                 kde=False)\nplt.title('Age of All Customers')\nplt.show(g)\n# age of customers who bought the bestsellers\ng = sns.histplot(bestsellers_contributors['age'], #Plot univariate distribution\n                 kde=False)\nplt.title('Age of Customers Who Bought Bestsellers')\nplt.show(g)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:34.817141Z","iopub.execute_input":"2022-03-02T06:20:34.817398Z","iopub.status.idle":"2022-03-02T06:20:37.105251Z","shell.execute_reply.started":"2022-03-02T06:20:34.817367Z","shell.execute_reply":"2022-03-02T06:20:37.104419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Comparing the age distribution of all customers and that of customers who bought the bestsellers, the distributions look similar. The bestsellers were catering to **all ages** of the customer base. This may be the reason why they became bestsellers.","metadata":{}},{"cell_type":"markdown","source":"### How are the bestsellers priced?\n*NOTE: The price data is transformed from the original currency values, so the values do not mean the actual price in any currency. The data providers did not provide information on how the price data is transformed.*","metadata":{}},{"cell_type":"code","source":"# drop duplicates such that each article at each price point is only considered once\ndf_transactions_single = df_transactions.drop_duplicates()\n\n# price\ng = sns.boxplot(x=df_transactions_single['price'])\nplt.title('Price of All Articles')\nplt.show(g)\n\ng = sns.boxplot(x=df_transactions_single[~df_transactions_single['article_id'].isin(bestsellers['article_id'])]['price'])\nplt.title('Price of Non-Bestselling Articles')\nplt.show(g)\n\ng = sns.boxplot(x=df_transactions_single[df_transactions_single['article_id'].isin(bestsellers['article_id'])]['price'])\nplt.title('Price of Bestselling Articles')\nplt.show(g)\n","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:37.106411Z","iopub.execute_input":"2022-03-02T06:20:37.106654Z","iopub.status.idle":"2022-03-02T06:20:54.132660Z","shell.execute_reply.started":"2022-03-02T06:20:37.106623Z","shell.execute_reply":"2022-03-02T06:20:54.131984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Duplicates of transactions are removed so that every article at each price point is only considered once in the analysis of price distribution. The price distribution of non-bestselling articles is similar to all transactions, that is positively skewed. Most bestselling articles are the relatively **cheaper** offerings. None of the more expensive items (`price` > 0.25) made it to the bestsellers.","metadata":{}},{"cell_type":"markdown","source":"### Which articles generate the most revenue? Are they the cheaper bestselling items or more expensive items?\n\nSince the prices are not the actual currency values and no cost data is provided, we cannot calculate and analyse the profits, so we will stick to analysing revenue. The absolute value of the revenues do not mean anything, it is just used for comparison among articles.","metadata":{}},{"cell_type":"code","source":"article_revenue = df_transactions.groupby('article_id').sum()\narticle_revenue.drop(columns=['customer_id', 'sales_channel_id', 'year', 'month', 'day'], inplace=True)\narticle_revenue_ranking = article_revenue.sort_values(by='price', ascending=False)\narticle_revenue_ranking.rename(columns={'price':'total_revenue_2019'}, inplace=True)\narticle_revenue_ranking.head(10)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:54.133751Z","iopub.execute_input":"2022-03-02T06:20:54.134080Z","iopub.status.idle":"2022-03-02T06:20:56.060100Z","shell.execute_reply.started":"2022-03-02T06:20:54.134054Z","shell.execute_reply":"2022-03-02T06:20:56.059266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The first two articles actually correspond to the top 2 bestsellers discovered earlier.","metadata":{}},{"cell_type":"markdown","source":"From before, there are 105542 distinct `article_id` in the articles dataset. Hence we define the **top 1000** (~1%) articles bringing in the most revenue as the **top_performers**. ","metadata":{}},{"cell_type":"code","source":"# add 2019 revenue data to df_articles\narticle_revenue = df_transactions.groupby('article_id').sum()\ndef f(x):\n    try:\n        return article_revenue.loc[x]['price']\n    except:\n        return 0\ndf_articles['total_revenue_2019'] = df_articles['article_id'].apply(f)\ndf_articles","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:20:56.061755Z","iopub.execute_input":"2022-03-02T06:20:56.062313Z","iopub.status.idle":"2022-03-02T06:21:03.235942Z","shell.execute_reply.started":"2022-03-02T06:20:56.062267Z","shell.execute_reply":"2022-03-02T06:21:03.235069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"top_performers = df_articles.sort_values(by='total_revenue_2019', ascending=False).head(1000)\n# New column: 1 if article is bestseller AND top_performer, else 0\ndf_articles['bestseller_revenue'] = df_articles['article_id'].isin(top_performers['article_id']).astype(int) * df_articles['article_id'].isin(bestsellers['article_id']).astype(int)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.237203Z","iopub.execute_input":"2022-03-02T06:21:03.237435Z","iopub.status.idle":"2022-03-02T06:21:03.285378Z","shell.execute_reply.started":"2022-03-02T06:21:03.237408Z","shell.execute_reply":"2022-03-02T06:21:03.284709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Number of articles that are both bestselling and top performing:\", df_articles['bestseller_revenue'].sum())","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.286577Z","iopub.execute_input":"2022-03-02T06:21:03.287252Z","iopub.status.idle":"2022-03-02T06:21:03.292649Z","shell.execute_reply.started":"2022-03-02T06:21:03.287213Z","shell.execute_reply":"2022-03-02T06:21:03.292052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**58.7%** of the bestsellers are also top performing (i.e. contributes to the top ~1% of revenue).","metadata":{}},{"cell_type":"code","source":"# plt.figure(figsize=(8,5))\n# g = sns.countplot(x=\"index_group_name\", \n#                   data=df_articles,\n#                   palette=\"husl\")\n# g.bar_label(g.containers[0])\n# g.tick_params(axis='x', rotation=90)\n# plt.title('All Articles on H&M')\n# plt.show(g)\nplt.figure(figsize=(8,5))\ng = sns.countplot(x=\"index_group_name\", \n                  data=top_performers,\n                  palette=\"pastel\")\ng.bar_label(g.containers[0])\ng.tick_params(axis='x', rotation=90)\nplt.title('Top Performing Articles on H&M')\nplt.show(g)","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.293954Z","iopub.execute_input":"2022-03-02T06:21:03.294150Z","iopub.status.idle":"2022-03-02T06:21:03.459054Z","shell.execute_reply.started":"2022-03-02T06:21:03.294125Z","shell.execute_reply":"2022-03-02T06:21:03.458043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Again, similar to the bestsellers, most customers that contribute to the revenue of H&M articles belong to the female demographic. Although H&M produces a lot of Baby/Children articles, none of them made it to the top performers. \n\nThe distribution is similar to the bestsellers. Let's see if the sales and revenues are correlated.","metadata":{}},{"cell_type":"code","source":"#df['A'].corr(df['B'])\ndf_articles['total_sales_2019'].corr(df_articles['total_revenue_2019'])","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.460860Z","iopub.execute_input":"2022-03-02T06:21:03.461846Z","iopub.status.idle":"2022-03-02T06:21:03.472074Z","shell.execute_reply.started":"2022-03-02T06:21:03.461803Z","shell.execute_reply":"2022-03-02T06:21:03.470978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Unsurprisingly, they are strongly correlated.","metadata":{}},{"cell_type":"markdown","source":"### How does each group of articles contribute to the revenue of H&M?\nLet us look at the breakdown of revenue by `index_group_name`.","metadata":{}},{"cell_type":"code","source":"index_group_revenue = df_articles[['index_group_name','total_revenue_2019']].groupby('index_group_name').total_revenue_2019.sum().reset_index()\nindex_group_revenue","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.473896Z","iopub.execute_input":"2022-03-02T06:21:03.475058Z","iopub.status.idle":"2022-03-02T06:21:03.499513Z","shell.execute_reply.started":"2022-03-02T06:21:03.475012Z","shell.execute_reply":"2022-03-02T06:21:03.498647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(8,8))\ncolors = sns.color_palette('pastel')\nplt.pie(x=index_group_revenue['total_revenue_2019'], labels=index_group_revenue['index_group_name'], colors=colors, autopct='%1.1f%%')\nplt.title('Revenue Contribution by Index Group')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.500983Z","iopub.execute_input":"2022-03-02T06:21:03.501355Z","iopub.status.idle":"2022-03-02T06:21:03.628560Z","shell.execute_reply.started":"2022-03-02T06:21:03.501312Z","shell.execute_reply":"2022-03-02T06:21:03.627632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ladieswear and Divided, which are both feminine styles, contribute to **88.5%** of revenue in 2019.","metadata":{}},{"cell_type":"markdown","source":"### Focusing on the #1 bestseller / top performer, how do its price and sales vary along time?","metadata":{}},{"cell_type":"code","source":"list(df_articles[df_articles['article_id'] == 706016001]['detail_desc'])[0]","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.630240Z","iopub.execute_input":"2022-03-02T06:21:03.630544Z","iopub.status.idle":"2022-03-02T06:21:03.638455Z","shell.execute_reply.started":"2022-03-02T06:21:03.630501Z","shell.execute_reply":"2022-03-02T06:21:03.637691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num1_transactions = df_transactions[df_transactions['article_id'] == 706016001]\nnum1_transactions.tail()","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.640168Z","iopub.execute_input":"2022-03-02T06:21:03.640738Z","iopub.status.idle":"2022-03-02T06:21:03.678882Z","shell.execute_reply.started":"2022-03-02T06:21:03.640695Z","shell.execute_reply":"2022-03-02T06:21:03.678119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Interestingly, the price of the same article on the same day could be different.\n\nWe calculate the daily average price for further analysis.","metadata":{}},{"cell_type":"code","source":"num1_day = num1_transactions.groupby(['t_dat']).mean()\n#num1_day_sales = num1_transactions.groupby(['t_dat']).count()\nnum1_day['daily_sales'] = num1_transactions.groupby(['t_dat']).count()['customer_id']\nnum1_day","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.684219Z","iopub.execute_input":"2022-03-02T06:21:03.684782Z","iopub.status.idle":"2022-03-02T06:21:03.724789Z","shell.execute_reply.started":"2022-03-02T06:21:03.684733Z","shell.execute_reply":"2022-03-02T06:21:03.724155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"article_id_of_interest = 706016001\n\nplt.rc('figure', figsize=(25, 8))   # this is to overwrite default aspect of graph to make x-axis longer\n\nfig, ax1 = plt.subplots()\nax1.plot(num1_day.index, num1_day['price'], color='#2ca02c')\nax1.set_ylabel('Daily Average Price (scaled)', color='#2ca02c')\nax1.tick_params('y', colors='#2ca02c')\nax1.set_ylim(bottom=max(num1_day['price'].min()-num1_day['price'].mean(), 0))\nax2 = plt.twinx()\nax2.bar(num1_day.index, num1_day['daily_sales'], color='#17becf')\nax2.set_ylabel('Daily Sales', color='#17becf')\nax2.tick_params('y', colors='#17becf')\nax2.set_ylim(top=num1_day['daily_sales'].max()+num1_day['daily_sales'].mean())\nplt.title('Daily Sales and Prices of article {}'.format(article_id_of_interest))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:03.726744Z","iopub.execute_input":"2022-03-02T06:21:03.727611Z","iopub.status.idle":"2022-03-02T06:21:04.566385Z","shell.execute_reply.started":"2022-03-02T06:21:03.727544Z","shell.execute_reply":"2022-03-02T06:21:04.565477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num1_day.sort_values(by='daily_sales', ascending=False).head()","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:04.567733Z","iopub.execute_input":"2022-03-02T06:21:04.568608Z","iopub.status.idle":"2022-03-02T06:21:04.586209Z","shell.execute_reply.started":"2022-03-02T06:21:04.568545Z","shell.execute_reply":"2022-03-02T06:21:04.585634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that price dips in Autumn and Winter results in strong peaks in the daily sales. Price dips in other months were less impactful on the daily sales. The lowest price dip occured during Black Friday, which had significant sales.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,5))\nsns.scatterplot(x='price',y='daily_sales',data=num1_day)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:04.587310Z","iopub.execute_input":"2022-03-02T06:21:04.587702Z","iopub.status.idle":"2022-03-02T06:21:04.753551Z","shell.execute_reply.started":"2022-03-02T06:21:04.587660Z","shell.execute_reply":"2022-03-02T06:21:04.752663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are very little datapoints at the lower prices but it is obvious that lower prices generate more sales when price < 0.03.","metadata":{}},{"cell_type":"markdown","source":"### What about other articles? How are their sales and price trends different or similar to the #1 bestseller?","metadata":{}},{"cell_type":"code","source":"import os\nimport matplotlib.image as mpimg\n\ndef view_article_trend(article_id_of_interest):\n    \n    # find image of article\n    file_path = '/kaggle/input/h-and-m-personalized-fashion-recommendations/images/0{}/0{}.jpg'.format(str(article_id_of_interest)[:2],article_id_of_interest)\n    if os.path.exists(file_path):\n        img = mpimg.imread(file_path)\n        #plt.imshow(img)\n    else:\n        img = None\n\n    # calculate the daily sales and average prices \n    article_daily_sales = df_transactions.groupby(['article_id','t_dat'])['article_id'].count()\n    article_daily_sales = article_daily_sales.reset_index(name='daily_sales')\n    article_daily_price = df_transactions.groupby(['article_id','t_dat'])['price'].mean()\n    article_daily_price = article_daily_price.reset_index(name='avg_price')\n    article_daily_price = article_daily_price[article_daily_price['article_id'] == article_id_of_interest]\n    article_daily_sales = article_daily_sales[article_daily_sales['article_id'] == article_id_of_interest]\n    article_daily_sales['avg_price'] = article_daily_price['avg_price']\n\n    # plot daily price vs sales\n    fig, (ax1, ax2) = plt.subplots(1, 2)\n    sns.scatterplot(x='avg_price',y='daily_sales',data=article_daily_sales, ax=ax1)\n    ax1.title.set_text('Price vs Sales of article {}'.format(article_id_of_interest))\n    # display image of article\n    if img is not None:\n        ax2.imshow(img)\n        ax2.title.set_text('Image of article {}'.format(article_id_of_interest))\n    else:\n        ax2.title.set_text('No image found.')\n        plt.show()\n\n    # plot temporal change in price and sales\n    fig, ax1 = plt.subplots()\n    ax1.plot(article_daily_sales['t_dat'], article_daily_sales['avg_price'], color='#2ca02c')\n    ax1.set_ylabel('Daily Average Price (scaled)', color='#2ca02c')\n    ax1.tick_params('y', colors='#2ca02c')\n    ax1.set_ylim(bottom=max(article_daily_sales['avg_price'].min()-article_daily_sales['avg_price'].mean(), 0))\n    ax2 = plt.twinx()\n    ax2.bar(article_daily_sales['t_dat'], article_daily_sales['daily_sales'], color='#17becf')\n    ax2.set_ylabel('Daily Sales', color='#17becf')\n    ax2.tick_params('y', colors='#17becf')\n    ax2.set_ylim(top=article_daily_sales['daily_sales'].max()+article_daily_sales['daily_sales'].mean())\n    plt.title('Daily Sales and Prices of article {}'.format(article_id_of_interest))\n    plt.show()\n\n    print('Article {}:'.format(article_id_of_interest))\n    print(list(df_articles[df_articles['article_id']==article_id_of_interest]['detail_desc'])[0])","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:04.755210Z","iopub.execute_input":"2022-03-02T06:21:04.755763Z","iopub.status.idle":"2022-03-02T06:21:04.769220Z","shell.execute_reply.started":"2022-03-02T06:21:04.755713Z","shell.execute_reply":"2022-03-02T06:21:04.768135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"view_article_trend(108775015) # [Insert article_id that we are interested in exploring]","metadata":{"execution":{"iopub.status.busy":"2022-03-02T06:21:04.770562Z","iopub.execute_input":"2022-03-02T06:21:04.770904Z","iopub.status.idle":"2022-03-02T06:21:13.929196Z","shell.execute_reply.started":"2022-03-02T06:21:04.770861Z","shell.execute_reply":"2022-03-02T06:21:13.928646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"For article 108775015, \n- From the scatterplot we can see that reducing its price does not increase its sales. \n- Looking at the daily trends, firstly we see that sales were higher in the first half of the year. The price dips in February till May cause spikes in sales. \n- Price dips occurred most significantly in the later part of the year, which is the winter season in the Northen Hemisphere. Looking at the image of the article, it is thus not surprising that sales were lower when the weather is cold.\n- One thing unusual is the low sales during summer (mid-May till August). Further data regarding marketing strategy, actual location of buyers (instead of encoded zip codes that do not give any geographical insights) may be helpful.","metadata":{}},{"cell_type":"markdown","source":"# Next Steps\nSome directions that I hope to work on moving forward:\n1. Frequent Pattern Mining - \"Customers who bought article A freqeuntly also bought ... \"\n2. Recommender System - Collaborative Filtering, Content-Based Recommendation","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}