{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Thêm thư viện\nimport pandas as pd\n#thay pandas -> cudf cho lej honw :> \nimport cudf as cf\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport squarify\nfrom sklearn.cluster import KMeans\nfrom sklearn.preprocessing import StandardScaler\nfrom statsmodels.tsa.seasonal import seasonal_decompose\nfrom statsmodels.tsa.arima.model import ARIMA\nfrom scipy.signal import argrelextrema\n\n\n# Thiết lập kiểu hiển thị\n%matplotlib inline\nsns.set_style(\"whitegrid\")\nsns.set_palette(\"husl\")\n\n# Đọc dữ liệu\ncustomers = pd.read_csv('/kaggle/input/h-and-m-personalized-fashion-recommendations/customers.csv')\narticles = pd.read_csv('/kaggle/input/h-and-m-personalized-fashion-recommendations/articles.csv')\ntransactions = pd.read_csv('/kaggle/input/h-and-m-personalized-fashion-recommendations/transactions_train.csv')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-27T17:28:31.674905Z","iopub.execute_input":"2025-03-27T17:28:31.67532Z","iopub.status.idle":"2025-03-27T17:29:49.321177Z","shell.execute_reply.started":"2025-03-27T17:28:31.675288Z","shell.execute_reply":"2025-03-27T17:29:49.319895Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"### Làm sạch dữ liệu\")\n# Xử lý dữ liệu khách hàng\ncustomers[\"age\"] = customers[\"age\"].fillna(customers[\"age\"].median()).astype(int).clip(16, 100)\ncustomers[[\"FN\", \"Active\"]] = customers[[\"FN\", \"Active\"]].fillna(0).astype(int)\ncustomers[[\"club_member_status\", \"fashion_news_frequency\"]] = customers[\n    [\"club_member_status\", \"fashion_news_frequency\"]\n].fillna(\"UNKNOWN\").apply(lambda x: x.str.lower().str.strip())\nprint(\"Số giá trị thiếu sau làm sạch (customers):\", customers.isnull().sum().sum())\nprint(\"5 dòng đầu tiên (customers):\")\ndisplay(customers.head())\n\n# Xử lý dữ liệu sản phẩm\nprint(\"\\n### Làm sạch articles.csv\")\n# Kiểm tra và xóa cột 'detail_desc' nếu tồn tại\nif 'detail_desc' in articles.columns:\n    articles = articles.drop(columns=[\"detail_desc\"])\nelse:\n    print(\"Cột 'detail_desc' không tồn tại trong DataFrame articles.\")\narticles = articles.dropna(subset=[\"article_id\", \"product_type_name\"])\narticles[[\"product_type_name\", \"colour_group_name\"]] = articles[\n    [\"product_type_name\", \"colour_group_name\"]\n].apply(lambda x: x.str.lower().str.strip())\nprint(\"Số giá trị thiếu sau làm sạch (articles):\", articles.isnull().sum().sum())\nprint(\"5 dòng đầu tiên (articles):\")\ndisplay(articles.head())\n\n# Xử lý giao dịch\nprint(\"\\n### Làm sạch transactions_train.csv\")\ntransactions[\"t_dat\"] = pd.to_datetime(transactions[\"t_dat\"], errors=\"coerce\")\ntransactions = transactions.dropna(subset=[\"t_dat\", \"customer_id\", \"article_id\"])\n# Sửa lỗi FutureWarning: Gán lại giá trị thay vì dùng inplace=True\ntransactions[\"price\"] = transactions[\"price\"].replace([np.inf, -np.inf], np.nan)\ntransactions[\"price\"] = transactions[\"price\"].fillna(transactions[\"price\"].median())\ntransactions[\"month\"] = transactions[\"t_dat\"].dt.month\ntransactions[\"year\"] = transactions[\"t_dat\"].dt.year\nprint(\"Số giá trị thiếu sau làm sạch (transactions):\", transactions.isnull().sum().sum())\nprint(\"5 dòng đầu tiên (transactions):\")\ndisplay(transactions.head())\n\n# Tổng hợp giao dịch theo khách hàng\ncustomer_summary = transactions.groupby(\"customer_id\").agg(\n    total_order_value=(\"price\", \"sum\"),\n    avg_order_value=(\"price\", \"mean\"),\n    transaction_count=(\"article_id\", \"count\"),\n    last_purchase=(\"t_dat\", \"max\"),\n).reset_index()\n\ndata = customers.merge(customer_summary, on=\"customer_id\", how=\"left\").fillna(0)\n\n# Tạo trans_articles (ghép transactions với articles)\ntrans_articles = pd.merge(transactions, articles[['article_id', 'product_type_name', 'colour_group_name', 'product_group_name']], \n                         on='article_id', how='left')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-27T18:11:36.487098Z","iopub.execute_input":"2025-03-27T18:11:36.488644Z","iopub.status.idle":"2025-03-27T18:12:19.422316Z","shell.execute_reply.started":"2025-03-27T18:11:36.488577Z","shell.execute_reply":"2025-03-27T18:12:19.421108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Tìm ngày bắt đầu và ngày kết thúc trong dataset\nstart_date = transactions['t_dat'].min()\nend_date = transactions['t_dat'].max()\n\nprint(f\"Ngày bắt đầu của dataset: {start_date.strftime('%Y-%m-%d')}\")\nprint(f\"Ngày kết thúc của dataset: {end_date.strftime('%Y-%m-%d')}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-27T18:34:48.878175Z","iopub.execute_input":"2025-03-27T18:34:48.878609Z","iopub.status.idle":"2025-03-27T18:34:49.050313Z","shell.execute_reply.started":"2025-03-27T18:34:48.878578Z","shell.execute_reply":"2025-03-27T18:34:49.049099Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"BẮT ĐẦU PHÂN TÍCH:\nSƠ LƯỢC VỀ H&M:\n- Một brand fastfashion nổi tiếng toàn cầu.\n- Hoạt động trong thị trường cạnh tranh cao.\n- Tuy là một brand lớn nhưng gắn liền với khái niệm 'fastfashion' và sản xuất chạy theo xu hướng, thị hiếu chứ không có dòng sản phẩm nổi bật cố định nào.\n\nĐÁNH GIÁ TRƯỚC KHI PHÂN TÍCH:\n- Phân khúc đánh vào tầm trung nên dữ liệu sẽ phản ánh gần giống với xu hướng của thị trường chung.\n- Các mặt hàng bán chạy sẽ là các mặt hàng cơ bản.\n- Khách hàng tiềm năng trẻ (<30).","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,5))\nsns.histplot(customers[\"age\"], bins=30, kde=True)\nplt.title(\"Phân bố độ tuổi của khách hàng\")\nplt.xlabel(\"Tuổi\")\nplt.ylabel(\"Số lượng khách hàng\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-27T17:21:44.597682Z","iopub.execute_input":"2025-03-27T17:21:44.598138Z","iopub.status.idle":"2025-03-27T17:21:50.976672Z","shell.execute_reply.started":"2025-03-27T17:21:44.598103Z","shell.execute_reply":"2025-03-27T17:21:50.975313Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Phân bố độ tuổi khá đúng với đánh giá ban đầu:\n- Nhóm khách hàng chiếm ưu thế là 20-28 tuổi.\n- Bất ngờ: 45-55 tuổi có thêm 1 cực đại.\n\n-> Phân tích: \n- Từ 20-28 tuổi mua nhiều là dễ hiểu (rẻ, chạy theo xu hướng).\n- Giảm dần về 40 tuổi -> Đây là giai đoạn có nhiều bước chuyển của con người.\n  + Nhánh tốt: sự nghiệp phát triển, bắt đầu chú trọng nhiều hơn đến ngoại hình (Hướng đến những thương hiệu cao cấp hơn).\n  + Nhánh khác: đối mặt với nhiều vấn đề trong cuộc sống (sự nghiệp, sức khỏe, gia đình,...) không còn chạy theo xu hướng (Hướng đến những dòng sản phẩm bình dân hơn). Tuy nhiên: điều này chỉ phù hợp với những nước đang phát triển.\n- Tăng lên sau 40 tuổi (đặc biệt từ 45 tuổi):\n  + Nhánh tốt (ban đầu): bắt đầu bớt chú trọng đến ngoại hình (Hướng đến sự tiện dụng).\n  + Nhánh khác (ban đầu): cuộc sống bắt đầu ổn định (Thoải mái hơn trong tiêu dùng).\n- Tổng quan: Dựa vào histogram này mình có thể thấy được 2 nhóm khách hàng tiềm năng của H&M cũng như dự đoán được nguyên do -> Hướng mở rộng (Mức chi tiêu cho H&M ở các nhóm tuổi, phân bổ sản phẩm ở các nhóm tuổi)","metadata":{}},{"cell_type":"code","source":"# Lọc dữ liệu từ ngày 1/10/2018 - 31/08/2020\ntransactions = transactions[(transactions['t_dat'] >= '2018-10-01') & (transactions['t_dat'] <= '2020-08-31')]\n# Tổng hợp doanh số theo tháng\nmonthly_sales_trend = transactions.groupby([\"year\", \"month\"]).size().reset_index(name=\"num_sales\")\nmonthly_sales_trend[\"date\"] = pd.to_datetime(monthly_sales_trend[[\"year\", \"month\"]].astype(str).agg(\"-\".join, axis=1) + \"-01\")\n\n# Tìm tháng có doanh số cao nhất & thấp nhất\nbest_period = monthly_sales_trend.loc[monthly_sales_trend[\"num_sales\"].idxmax()]\nworst_period = monthly_sales_trend.loc[monthly_sales_trend[\"num_sales\"].idxmin()]\n\n# Xác định cực đại & cực tiểu\nsales_values = monthly_sales_trend[\"num_sales\"].values\nmaxima_idx = argrelextrema(sales_values, np.greater)[0]\nminima_idx = argrelextrema(sales_values, np.less)[0]\n\n# Vẽ biểu đồ\nplt.figure(figsize=(12, 5))\nsns.lineplot(data=monthly_sales_trend, x=\"date\", y=\"num_sales\", marker=\"o\", label=\"Sales Trend\")\nplt.scatter(best_period[\"date\"], best_period[\"num_sales\"], color=\"green\", s=150, label=\"Best Period\")\nplt.scatter(worst_period[\"date\"], worst_period[\"num_sales\"], color=\"red\", s=150, label=\"Worst Period\")\nplt.scatter(monthly_sales_trend.loc[maxima_idx, \"date\"], monthly_sales_trend.loc[maxima_idx, \"num_sales\"], \n            color=\"blue\", s=80, label=\"Local Maxima\")\nplt.scatter(monthly_sales_trend.loc[minima_idx, \"date\"], monthly_sales_trend.loc[minima_idx, \"num_sales\"], \n            color=\"orange\", s=80, label=\"Local Minima\")\nplt.title(\"Xu hướng doanh số hàng tháng (từ 10/2018 - 08/2020)\", fontsize=14)\nplt.xlabel(\"Thời gian\", fontsize=12)\nplt.ylabel(\"Số lượng giao dịch\", fontsize=12)\nplt.legend()\nplt.grid()\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()\n\n# In kết quả thống kê\nprint(f\"🔥 Thời gian bán chạy nhất: {best_period['date'].strftime('%Y-%m')} ({best_period['num_sales']:,} sales)\")\nprint(f\"❄️ Thời gian bán kém nhất: {worst_period['date'].strftime('%Y-%m')} ({worst_period['num_sales']:,} sales)\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-27T18:38:54.413764Z","iopub.execute_input":"2025-03-27T18:38:54.414208Z","iopub.status.idle":"2025-03-27T18:38:57.749546Z","shell.execute_reply.started":"2025-03-27T18:38:54.414177Z","shell.execute_reply":"2025-03-27T18:38:57.748331Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Mạnh hè-xuân hè:\n- chất liệu\n- giá\n- mẫu mã\nYếu đông-đông xuân\n- chất liệu -> giá\n- cân nhắc sp lâu dài\n- mẫu mã\n\nCải thiện + phát huy","metadata":{}},{"cell_type":"code","source":"# Gộp transactions với articles để lấy thông tin màu sắc\nmerged_data = transactions.merge(articles, on=\"article_id\", how=\"left\")  \n\n# Nhóm theo năm, tháng và màu sắc, đếm số lượng sản phẩm bán ra\ncolor_trends = merged_data.groupby([\"year\", \"month\", \"colour_group_name\"]).size().reset_index(name=\"count\")\n\n# Lọc top 5 màu bán chạy nhất\ntop_5_colors = merged_data[\"colour_group_name\"].value_counts().head(5).index\ncolor_trends_filtered = color_trends[color_trends[\"colour_group_name\"].isin(top_5_colors)]\n\n# Vẽ biểu đồ xu hướng màu sắc theo thời gian\nplt.figure(figsize=(12, 5))\nsns.lineplot(data=color_trends_filtered, x=\"year\", y=\"count\", hue=\"colour_group_name\", marker=\"o\")  # Thay 'sales' bằng 'count'\nplt.title(\"Top 5 Color Trends Over Time\")\nplt.xlabel(\"Year\")\nplt.ylabel(\"Number of Sales\")\nplt.legend(title=\"Color\", bbox_to_anchor=(1, 1))  # Đưa legend ra ngoài để không bị rối\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-28T03:57:12.901009Z","iopub.execute_input":"2025-03-28T03:57:12.901306Z","iopub.status.idle":"2025-03-28T03:57:12.995863Z","shell.execute_reply.started":"2025-03-28T03:57:12.901281Z","shell.execute_reply":"2025-03-28T03:57:12.994343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Màu theo mùa\nMàu theo tuổi\nMàu theo dòng sản phẩm","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n#Họ mua gì và tại sao?\nprint(\"Câu hỏi: Sản phẩm nào bán chạy nhất, và nhóm tuổi nào thích chúng?\")\n# Tổng hợp doanh số và số giao dịch theo loại sản phẩm\nproduct_sales = trans_articles.groupby('product_type_name').agg({'article_id': 'count', 'price': 'sum'}).reset_index()\nproduct_sales.columns = ['product_type_name', 'transaction_count', 'total_revenue']\ntop_products = product_sales.sort_values('transaction_count', ascending=False).head(5)\nplt.figure(figsize=(10, 6))\nsns.barplot(x='product_type_name', y='transaction_count', data=top_products)\nplt.title('Top 5 sản phẩm theo số giao dịch', fontsize=14)\nplt.xlabel('Loại sản phẩm', fontsize=12)\nplt.ylabel('Số giao dịch', fontsize=12)\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()\nprint(f\"- Top sản phẩm: `trousers` ({top_products.iloc[0]['transaction_count']:,} giao dịch, {top_products.iloc[0]['total_revenue']:.2f} USD).\")\n\n# Phân tích sở thích sản phẩm theo nhóm tuổi\nyoung_trans = trans_articles[trans_articles['customer_id'].isin(data[data['age'].between(23, 27)]['customer_id'])]\nold_trans = trans_articles[trans_articles['customer_id'].isin(data[data['age'] >= 50]['customer_id'])]\nyoung_products = young_trans['product_type_name'].value_counts().head(3)\nold_products = old_trans['product_type_name'].value_counts().head(3)\nprint(\"Top 3 sản phẩm theo độ tuổi:\")\nprint(f\"23-27 tuổi:\\n{young_products}\\n50+ tuổi:\\n{old_products}\")\n\n# Phân tích sản phẩm bán chạy theo 4 mùa\nprint(\"\\n### Phân tích sản phẩm bán chạy theo 4 mùa trong năm\")\n\n# Định nghĩa các mùa\nseasons = {\n    'Xuân (Tháng 3-5)': [3, 4, 5],\n    'Hạ (Tháng 6-8)': [6, 7, 8],\n    'Thu (Tháng 9-11)': [9, 10, 11],\n    'Đông (Tháng 12, 1-2)': [12, 1, 2]\n}\n\n# Tạo danh sách để lưu top sản phẩm theo mùa\nseasonal_top_products = {}\n\n# Lặp qua từng mùa để phân tích\nfor season_name, months in seasons.items():\n    # Lọc dữ liệu theo mùa\n    season_data = trans_articles[trans_articles['month'].isin(months)]\n    # Tổng hợp số giao dịch theo loại sản phẩm\n    season_sales = season_data.groupby('product_type_name').agg({'article_id': 'count'}).reset_index()\n    season_sales.columns = ['product_type_name', 'transaction_count']\n    # Lấy top 5 sản phẩm\n    top_season_products = season_sales.sort_values('transaction_count', ascending=False).head(5)\n    seasonal_top_products[season_name] = top_season_products\n\n    # Vẽ biểu đồ cột cho mùa này\n    plt.figure(figsize=(10, 6))\n    sns.barplot(x='product_type_name', y='transaction_count', data=top_season_products, palette='coolwarm')\n    plt.title(f'Top 5 sản phẩm bán chạy trong {season_name}', fontsize=14)\n    plt.xlabel('Loại sản phẩm', fontsize=12)\n    plt.ylabel('Số giao dịch', fontsize=12)\n    plt.xticks(rotation=45)\n    plt.tight_layout()\n    plt.show()\n\n    # In thông tin chi tiết\n    print(f\"\\nTop 5 sản phẩm trong {season_name}:\")\n    print(top_season_products)\n    print(f\"- Sản phẩm dẫn đầu {season_name}: `{top_season_products.iloc[0]['product_type_name']}` với {top_season_products.iloc[0]['transaction_count']:,} giao dịch.\")\n\n# So sánh sản phẩm dẫn đầu giữa các mùa\nprint(\"\\n### So sánh sản phẩm dẫn đầu giữa các mùa\")\nleading_products = {season: products.iloc[0] for season, products in seasonal_top_products.items()}\nleading_df = pd.DataFrame([\n    {'Mùa': season, 'Sản phẩm dẫn đầu': row['product_type_name'], 'Số giao dịch': row['transaction_count']}\n    for season, row in leading_products.items()\n])\nprint(leading_df)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# 4.5 Xu hướng mua sắm theo danh mục sản phẩm\ngroup_sales = df_merged.groupby(\"product_group_name\")[\"price\"].sum().sort_values(ascending=False)\nplt.figure(figsize=(12,6))\nsns.barplot(x=group_sales.index, y=group_sales.values)\nplt.xticks(rotation=90)\nplt.title(\"Doanh thu theo nhóm sản phẩm\")\nplt.xlabel(\"Nhóm sản phẩm\")\nplt.ylabel(\"Doanh thu\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-27T17:26:12.130732Z","iopub.execute_input":"2025-03-27T17:26:12.131196Z","iopub.status.idle":"2025-03-27T17:26:15.008323Z","shell.execute_reply.started":"2025-03-27T17:26:12.131166Z","shell.execute_reply":"2025-03-27T17:26:15.006893Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 3️⃣ Product Preferences\npopular_products = transactions[\"article_id\"].value_counts().head(10).reset_index()\npopular_products = popular_products.merge(articles[[\"article_id\", \"prod_name\"]], on=\"article_id\")\n\nplt.figure(figsize=(12, 5))\nsns.barplot(x=popular_products[\"prod_name\"], y=popular_products[\"count\"], palette=\"viridis\")\nplt.xticks(rotation=45, ha=\"right\")  # Xoay chữ để dễ nhìn hơn\nplt.title(\"Top 10 Best-Selling Products\")\nplt.xlabel(\"Product Name\")\nplt.ylabel(\"Number of Sales\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-27T18:02:31.386728Z","iopub.execute_input":"2025-03-27T18:02:31.38708Z","iopub.status.idle":"2025-03-27T18:02:33.656559Z","shell.execute_reply.started":"2025-03-27T18:02:31.387052Z","shell.execute_reply":"2025-03-27T18:02:33.655236Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"ủa cái theo ngày đâu mất tiêu r??","metadata":{}}]}