diff --git a/homework/m1_numpy.ipynb b/homework/m1_numpy.ipynb
new file mode 100644
index 0000000..fcb4076
--- /dev/null
+++ b/homework/m1_numpy.ipynb
@@ -0,0 +1,382 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "dedf1249",
+ "metadata": {},
+ "source": [
+ "\"\"\"\n",
+ "M1 NumPy 向量化思維 — 課後作業\n",
+ "================================\n",
+ "請完成以下每個函式,用 NumPy 向量化寫法(不要 for-loop)。\n",
+ "完成後 git push,GitHub Actions 會自動批改並顯示成績與解答。\n",
+ "\n",
+ "提示:\n",
+ "- np.array, np.where, np.argsort\n",
+ "- 布林遮罩: arr[arr > 10]\n",
+ "- 統計: .sum(), .mean(), .max(), .min()\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60c0496d",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟢 送分題(每題 10 分,共 30 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "5567ab7e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "de47a63f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "import numpy as np\n",
+ "\n",
+ "\n",
+ "\n",
+ "def green_mean():\n",
+ " \"\"\"建立 [10, 20, 30, 40, 50],回傳所有元素的平均值 (float)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "def green_double():\n",
+ " \"\"\"建立 [10, 20, 30, 40, 50],回傳所有元素乘以 2 的 ndarray\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "def green_filter():\n",
+ " \"\"\"建立 [10, 20, 30, 40, 50],回傳大於 25 的元素 (ndarray)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "378063f7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "30.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "\n",
+ "#def green_mean():\n",
+ " #\"\"\"建立 [10, 20, 30, 40, 50],回傳所有元素的平均值 (float)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " \n",
+ "arr = np.array([10, 20, 30, 40, 50])\n",
+ "avg_arr = np.mean(arr)\n",
+ "print(avg_arr)\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "d62c7972",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[ 20 40 60 80 100]\n"
+ ]
+ }
+ ],
+ "source": [
+ "#def green_double():\n",
+ "#\"\"\"建立 [10, 20, 30, 40, 50],回傳所有元素乘以 2 的 ndarray\"\"\"\n",
+ "# TODO: 你的程式碼\n",
+ "\n",
+ "arr = np.array([10, 20, 30, 40, 50])\n",
+ "twotimes_arr = np.multiply(arr, 2)\n",
+ "print(twotimes_arr)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "d70bddec",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[30 40 50]\n"
+ ]
+ }
+ ],
+ "source": [
+ "#def green_filter():\n",
+ " #\"\"\"建立 [10, 20, 30, 40, 50],回傳大於 25 的元素 (ndarray)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "arr = np.array([10, 20, 30, 40, 50])\n",
+ "biggerthan25_arr = arr[arr > 25]\n",
+ "print(biggerthan25_arr)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "df18d551",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟡 核心題(每題 15 分,共 45 分)\n",
+ "# 以下函式會接收從 products.csv 讀出的 prices, stocks 陣列\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "02a97124",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "def yellow_expensive_count(prices):\n",
+ " \"\"\"回傳單價 > 1000 的商品數量 (int)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "def yellow_top3_stock_indices(stocks):\n",
+ " \"\"\"\n",
+ " 回傳庫存最多的前 3 個商品的索引位置 (ndarray, 由大到小排)\n",
+ " 提示:np.argsort\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "def yellow_restock_cost(prices, stocks):\n",
+ " \"\"\"\n",
+ " 單價 < 500 的商品,每種各進貨 50 個,回傳總花費 (float/int)\n",
+ " 提示:布林遮罩 + .sum()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "24269aa8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "df = pd.read_csv(r\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\products.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "e328bf6b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "16"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "\n",
+ "DATA = pd.read_csv(r\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\products.csv\")\n",
+ "prices = DATA.iloc[:, 3].to_numpy()\n",
+ "stocks = DATA.iloc[:, 4].to_numpy()\n",
+ "#def yellow_expensive_count(prices):\n",
+ "#\"\"\"回傳單價 > 1000 的商品數量 (int)\"\"\"\n",
+ "# TODO: 你的程式碼\n",
+ "\n",
+ "prices \n",
+ "prices[prices > 1000]\n",
+ "len(prices[prices > 1000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "8f9d602b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([10, 0, 17, 22, 24, 5, 25, 2, 11, 13, 23, 1, 29, 20, 14, 12, 16,\n",
+ " 28, 21, 27, 19, 15, 4, 9, 26, 6, 18, 3, 8, 7])"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "\n",
+ "\n",
+ "DATA = pd.read_csv(r\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\products.csv\")\n",
+ "prices = DATA.iloc[:, 3].to_numpy()\n",
+ "stocks = DATA.iloc[:, 4].to_numpy()\n",
+ "\n",
+ "#def yellow_top3_stock_indices(stocks):\n",
+ " #\"\"\"\n",
+ " #回傳庫存最多的前 3 個商品的索引位置 (ndarray, 由大到小排)\n",
+ " #提示:np.argsort\n",
+ " #\"\"\"\n",
+ "\n",
+ "\n",
+ "stocks\n",
+ "np.argsort(stocks)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "62a610a4",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "np.int64(120300)"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "#def yellow_restock_cost(prices, stocks):\n",
+ "# \"\"\"\n",
+ "#單價 < 500 的商品,每種各進貨 50 個,回傳總花費 (float/int)\n",
+ "#提示:布林遮罩 + .sum()\n",
+ "#\"\"\"\n",
+ "# TODO: 你的程式碼\n",
+ " \n",
+ "prices[prices<500] #找出單價小於500的價格\n",
+ "prices[prices<500] * 50 #每個商品進貨50個\n",
+ "sum(prices[prices<500] * 50) #總價格"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3fa5a64a",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🔴 挑戰題(25 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b62c2097",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([1312.5, 1202.6, 203. , 426.3, 1075.9, 392.7, 766.5, 1238.3,\n",
+ " 526.4, 1677.2, 228.9, 219.8, 1292.2, 267.4, 189.7, 1460.9,\n",
+ " 133.7, 700. , 1132.6, 331.8, 410.9, 558. , 141.3, 1724.4,\n",
+ " 1386.9, 1329.3, 1755.9, 1935. , 1627. , 1506. ])"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\n",
+ "#def red_double11_prices(prices, stocks):\n",
+ "#\"\"\"\n",
+ "#雙 11 定價規則(必須向量化,不能用 for-loop):\n",
+ "#- 庫存 >= 100:打 7 折\n",
+ "#- 庫存 20~99:打 9 折\n",
+ "#- 庫存 < 20:原價\n",
+ "#回傳每個商品的雙 11 售價 (ndarray)\n",
+ "#提示:np.where 可以巢狀使用\n",
+ "#\"\"\"\n",
+ "\n",
+ "\n",
+ "prices_07 = prices[stocks >= 100] *0.7\n",
+ "prices_09 = prices[(stocks >= 20) & (stocks <= 99)] *0.9\n",
+ "prices_original = prices[stocks < 20]\n",
+ "\n",
+ "# np.concatenate 沿指定軸連接多個陣列\n",
+ "total_price = np.concatenate([prices_07, prices_09, prices_original])\n",
+ "total_price\n",
+ "\n",
+ " \n",
+ " "
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/homework/m2_pandas_cleaning.ipynb b/homework/m2_pandas_cleaning.ipynb
new file mode 100644
index 0000000..bb01c3c
--- /dev/null
+++ b/homework/m2_pandas_cleaning.ipynb
@@ -0,0 +1,502 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "2b540840",
+ "metadata": {},
+ "source": [
+ "\"\"\"\n",
+ "M2 Pandas I/O 與資料清理 — 課後作業\n",
+ "====================================\n",
+ "情境:你拿到一份「故意弄髒」的訂單 CSV (orders_raw.csv),\n",
+ "裡面有欄位名稱空格、金額帶 $ 符號、日期格式錯誤、缺值、重複列。\n",
+ "請用 Pandas 把它清乾淨。\n",
+ "\n",
+ "資料路徑:datasets/ecommerce/orders_raw.csv\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "1b8aaf52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "07b0ba0c",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟢 送分題(每題 10 分,共 30 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "fdd659ed",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "<>:7: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "<>:7: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "C:\\Users\\highm\\AppData\\Local\\Temp\\ipykernel_7304\\1966798927.py:7: SyntaxWarning: invalid escape sequence '\\p'\n",
+ " Data = \"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_raw.csv\"\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Order_ID | \n",
+ " customer_id | \n",
+ " Product_ID | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " $3,538 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5082 | \n",
+ " 2020 | \n",
+ " 1023 | \n",
+ " 3.0 | \n",
+ " NaN | \n",
+ " 4431 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 205 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135 | \n",
+ "
\n",
+ " \n",
+ " | 206 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750 | \n",
+ "
\n",
+ " \n",
+ " | 207 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580 | \n",
+ "
\n",
+ " \n",
+ " | 208 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436 | \n",
+ "
\n",
+ " \n",
+ " | 209 | \n",
+ " 5113 | \n",
+ " 2018 | \n",
+ " 1005 | \n",
+ " NaN | \n",
+ " 2025-08-13 | \n",
+ " 870 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
210 rows × 6 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Order_ID customer_id Product_ID qty order_date amount\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600\n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355\n",
+ "2 5123 2013 1013 2.0 2025-09-11 $3,538\n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618\n",
+ "4 5082 2020 1023 3.0 NaN 4431\n",
+ ".. ... ... ... ... ... ...\n",
+ "205 5041 2014 1001 5.0 2025-10-03 8135\n",
+ "206 5157 2005 1026 5.0 2025-01-02 10750\n",
+ "207 5134 2015 1012 5.0 2025-06-03 9580\n",
+ "208 5135 2010 1007 4.0 2025-09-05 2436\n",
+ "209 5113 2018 1005 NaN 2025-08-13 870\n",
+ "\n",
+ "[210 rows x 6 columns]"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def green_read_csv():\n",
+ " \"\"\"\n",
+ " 讀取 orders_raw.csv,回傳原始 DataFrame(不做任何清理)\n",
+ " 提示:pd.read_csv()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "Data = \"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_raw.csv\"\n",
+ "\n",
+ "raw = pd.read_csv(Data)\n",
+ "\n",
+ "raw"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "7377e019",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "(210, 6)\n"
+ ]
+ }
+ ],
+ "source": [
+ "def green_shape(df):\n",
+ " \"\"\"\n",
+ " 回傳 DataFrame 的 (列數, 欄數) tuple\n",
+ " 提示:df.shape\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "print(raw.shape)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "4f74c52b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Order_ID int64\n",
+ "customer_id int64\n",
+ "Product_ID int64\n",
+ " qty float64\n",
+ "order_date str\n",
+ "amount str\n",
+ "dtype: object\n"
+ ]
+ }
+ ],
+ "source": [
+ "def green_dtypes(df):\n",
+ " \"\"\"\n",
+ " 回傳 DataFrame 的欄位型別 (Series)\n",
+ " 提示:df.dtypes\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "print(raw.dtypes)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bd32df6f",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟡 核心題(每題 15 分,共 45 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "5190a78c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "RangeIndex: 210 entries, 0 to 209\n",
+ "Data columns (total 6 columns):\n",
+ " # Column Non-Null Count Dtype \n",
+ "--- ------ -------------- ----- \n",
+ " 0 Order_ID 210 non-null int64 \n",
+ " 1 customer_id 210 non-null int64 \n",
+ " 2 Product_ID 210 non-null int64 \n",
+ " 3 qty 196 non-null float64\n",
+ " 4 order_date 198 non-null str \n",
+ " 5 amount 210 non-null str \n",
+ "dtypes: float64(1), int64(3), str(2)\n",
+ "memory usage: 10.0 KB\n"
+ ]
+ }
+ ],
+ "source": [
+ "raw.info()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "92107d78",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "['order_id', 'customer_id', 'product_id', 'qty', 'order_date', 'amount']\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "<>:8: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "<>:8: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "C:\\Users\\highm\\AppData\\Local\\Temp\\ipykernel_7304\\112280071.py:8: SyntaxWarning: invalid escape sequence '\\p'\n",
+ " raw = pd.read_csv(\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_raw.csv\")\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_clean_columns(df):\n",
+ " \"\"\"\n",
+ " 清理欄位名稱:去除前後空白、全部轉小寫\n",
+ " 回傳清理後的 DataFrame(不要修改原始 df)\n",
+ " 提示:df.columns.str.strip().str.lower()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "raw = pd.read_csv(\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_raw.csv\")\n",
+ "\n",
+ "raw.columns = raw.columns.str.strip().str.lower()\n",
+ "\n",
+ "print(list(raw.columns))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "fa52c00b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "float64\n",
+ "count 210.000000\n",
+ "mean 3632.457143\n",
+ "std 2809.327116\n",
+ "min 157.000000\n",
+ "25% 1371.750000\n",
+ "50% 3000.000000\n",
+ "75% 5748.000000\n",
+ "max 11980.000000\n",
+ "Name: amount, dtype: float64\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_clean_amount(df):\n",
+ " \"\"\"\n",
+ " 清理 amount 欄位:移除 '$' 和 ',' 符號,轉為 float\n",
+ " 假設欄位名稱已經是小寫的 'amount'\n",
+ " 回傳清理後的 DataFrame(不要修改原始 df)\n",
+ " 提示:.str.replace() + .astype(float)\n",
+ " \"\"\"\n",
+ "\n",
+ "\n",
+ " # TODO: 你的程式碼\n",
+ "raw['amount'] = (\n",
+ " raw['amount']\n",
+ " .astype(str)\n",
+ " .str.replace('$', '', regex=False)\n",
+ " .str.replace(',', '', regex=False)\n",
+ " .astype(float)\n",
+ ")\n",
+ "print(raw['amount'].dtype)\n",
+ "print(raw['amount'].describe())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "a5ffaebf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def yellow_drop_duplicates(df):\n",
+ " \"\"\"\n",
+ " 移除完全重複的列,回傳去重後的 DataFrame\n",
+ " 提示:df.drop_duplicates()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "raw = raw.drop_duplicates()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0cb924ac",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🔴 挑戰題(25 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "9754ad1b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "<>:17: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "<>:17: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "C:\\Users\\highm\\AppData\\Local\\Temp\\ipykernel_7304\\995615519.py:17: SyntaxWarning: invalid escape sequence '\\p'\n",
+ " raw = pd.read_csv(\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_raw.csv\")\n"
+ ]
+ }
+ ],
+ "source": [
+ "def red_clean_orders(path):\n",
+ " \"\"\"\n",
+ " 完整清理 pipeline:一個函式搞定所有清理步驟\n",
+ " 1. 讀取 CSV\n",
+ " 2. 欄位名稱:去空白、轉小寫\n",
+ " 3. amount:移除 '$' ',',轉 float\n",
+ " 4. order_date:轉為 datetime(無法轉換的設為 NaT)\n",
+ " 5. 刪除 amount 或 order_date 為空的列\n",
+ " 6. 移除重複列\n",
+ "\n",
+ " 回傳:清理後的 DataFrame\n",
+ " 提示:pd.to_datetime(errors='coerce')\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " \n",
+ "\n",
+ "raw = pd.read_csv(\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_raw.csv\")\n",
+ "raw.columns = raw.columns.str.strip().str.lower()\n",
+ "raw['amount'] = (\n",
+ " raw['amount']\n",
+ " .astype(str)\n",
+ " .str.replace('$', '', regex=False)\n",
+ " .str.replace(',', '', regex=False)\n",
+ " .astype(float)\n",
+ ")\n",
+ "\n",
+ "raw['order_date'] = pd.to_datetime(raw['order_date'], errors='coerce')\n",
+ "raw = raw.dropna(subset=['order_date', 'amount'])\n",
+ "raw = raw.drop_duplicates()\n",
+ "\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/homework/m3_pandas_advanced.ipynb b/homework/m3_pandas_advanced.ipynb
new file mode 100644
index 0000000..0648725
--- /dev/null
+++ b/homework/m3_pandas_advanced.ipynb
@@ -0,0 +1,867 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9d185e68",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'\\nM3 Pandas 進階:merge / groupby / RFM — 課後作業\\n=================================================\\n情境:你已經有清理好的訂單資料,現在要合併客戶和商品表,\\n做出有商業價值的分析。\\n\\n資料路徑:\\n - datasets/ecommerce/orders_clean.csv\\n - datasets/ecommerce/customers.csv\\n - datasets/ecommerce/products.csv\\n'"
+ ]
+ },
+ "execution_count": 1,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\"\"\"\n",
+ "M3 Pandas 進階:merge / groupby / RFM — 課後作業\n",
+ "=================================================\n",
+ "情境:你已經有清理好的訂單資料,現在要合併客戶和商品表,\n",
+ "做出有商業價值的分析。\n",
+ "\n",
+ "資料路徑:\n",
+ " - datasets/ecommerce/orders_clean.csv\n",
+ " - datasets/ecommerce/customers.csv\n",
+ " - datasets/ecommerce/products.csv\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "88c33281",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b35b93e",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟢 送分題(每題 10 分,共 30 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "1a89ec7d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "分析基底: (188, 14)\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_name | \n",
+ " region | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " amount | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 8600.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 1355.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 3538.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618.0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_name region vip_level product_name category amount\n",
+ "0 5064 Victor Lin North Gold Dumbbell 5kg Sports 8600.0\n",
+ "1 5023 Zoe Huang South Platinum Throw Pillow Home 1355.0\n",
+ "2 5123 Mia Huang North Platinum Cotton T-Shirt Clothing 3538.0\n",
+ "3 5118 Emma Liu West Bronze Water Bottle Sports 1618.0\n",
+ "4 5161 Quinn Chen East Silver Coffee Mug Home 1846.0"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "#def green_load_and_merge():\n",
+ "\n",
+ "\"\"\"\n",
+ " 讀取三張表,合併成一張完整的 DataFrame 並回傳\n",
+ " - orders_clean.csv LEFT JOIN customers.csv ON customer_id\n",
+ " - 再 LEFT JOIN products.csv ON product_id\n",
+ " 提示:pd.merge(how='left')\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "\n",
+ "DATA = '../datasets/ecommerce'\n",
+ "orders = pd.read_csv(f'{DATA}/orders_clean.csv', parse_dates=['order_date'])\n",
+ "customers = pd.read_csv(f'{DATA}/customers.csv')\n",
+ "products = pd.read_csv(f'{DATA}/products.csv')\n",
+ "\n",
+ "df = (\n",
+ " orders\n",
+ " .merge(customers, on='customer_id', how='left')\n",
+ " .merge(products, on='product_id', how='left')\n",
+ ")\n",
+ "print('分析基底:', df.shape)\n",
+ "df[['order_id','customer_name','region','vip_level','product_name','category','amount']].head()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d5d9720b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "188\n"
+ ]
+ }
+ ],
+ "source": [
+ "def green_row_count(df):\n",
+ " \"\"\"回傳 DataFrame 的列數 (int)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "rows = len(df)\n",
+ "print(rows)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "2007b55b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Index(['order_id', 'customer_id', 'product_id', 'qty', 'order_date', 'amount',\n",
+ " 'customer_name', 'region', 'signup_date', 'vip_level', 'product_name',\n",
+ " 'category', 'unit_price', 'stock_qty'],\n",
+ " dtype='str')"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def green_column_list(df):\n",
+ " \"\"\"回傳 DataFrame 的所有欄位名稱 (list)\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "df.columns"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ace602f9",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟡 核心題(每題 15 分,共 45 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "687fb0c1",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "🏆 商品營收排名:\n",
+ "category\n",
+ "Books 182244.0\n",
+ "Sports 176315.0\n",
+ "Clothing 133841.0\n",
+ "Electronics 100235.0\n",
+ "Home 93753.0\n",
+ "Name: amount, dtype: float64\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_top_category(df):\n",
+ " \"\"\"\n",
+ " 哪個商品類別 (category) 的總營收最高?\n",
+ " 回傳該類別名稱 (str)\n",
+ " 提示:groupby('category')['amount'].sum()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "cat_rev = df.groupby('category')['amount'].sum().sort_values(ascending=False)\n",
+ "print('🏆 商品營收排名:')\n",
+ "print(cat_rev)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "71963f34",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "79\n",
+ "285982.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_gold_vip_stats(df):\n",
+ " \"\"\"\n",
+ " Gold VIP 客戶總共下了幾張訂單?總金額多少?\n",
+ " 回傳 tuple: (訂單數 int, 總金額 float)\n",
+ " 提示:df[df['vip_level'] == 'Gold']\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "#篩選出gold 客戶資料\n",
+ "vip_gold = df[df['vip_level'] == 'Gold']\n",
+ "#vip gold 訂單數量\n",
+ "gold_rows = len(vip_gold)\n",
+ "print(gold_rows) #79\n",
+ "\n",
+ "#總金額\n",
+ "vip_gold_total_rev = vip_gold['amount'].sum()\n",
+ "print(vip_gold_total_rev)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "53796a3e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "region\n",
+ "East 3318.000000\n",
+ "North 3738.044776\n",
+ "South 3786.152778\n",
+ "West 3340.848485\n",
+ "Name: amount, dtype: float64\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_region_avg_amount(df):\n",
+ " \"\"\"\n",
+ " 計算每個地區 (region) 的平均訂單金額\n",
+ " 回傳 Series(index=region, values=平均金額)\n",
+ " 提示:groupby('region')['amount'].mean()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "df\n",
+ "avg_region_rev = df.groupby('region')['amount'].mean()\n",
+ "print(avg_region_rev)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f349baf0",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🔴 挑戰題(25 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "6a3b95c2",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2026-04-30 23:46:09.133630\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " customer_id | \n",
+ " customer_name | \n",
+ " Recency | \n",
+ " Frequency | \n",
+ " Monetary | \n",
+ "
\n",
+ " \n",
+ " | customer_id | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 2001 | \n",
+ " 367 | \n",
+ " Alice Chen | \n",
+ " 367 | \n",
+ " 3 | \n",
+ " 16095.0 | \n",
+ "
\n",
+ " \n",
+ " | 2002 | \n",
+ " 483 | \n",
+ " Bob Wang | \n",
+ " 483 | \n",
+ " 7 | \n",
+ " 16211.0 | \n",
+ "
\n",
+ " \n",
+ " | 2003 | \n",
+ " 469 | \n",
+ " Carol Huang | \n",
+ " 469 | \n",
+ " 10 | \n",
+ " 23007.0 | \n",
+ "
\n",
+ " \n",
+ " | 2004 | \n",
+ " 463 | \n",
+ " David Chen | \n",
+ " 463 | \n",
+ " 7 | \n",
+ " 39085.0 | \n",
+ "
\n",
+ " \n",
+ " | 2005 | \n",
+ " 483 | \n",
+ " Emma Liu | \n",
+ " 483 | \n",
+ " 8 | \n",
+ " 34917.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " customer_id customer_name Recency Frequency Monetary\n",
+ "customer_id \n",
+ "2001 367 Alice Chen 367 3 16095.0\n",
+ "2002 483 Bob Wang 483 7 16211.0\n",
+ "2003 469 Carol Huang 469 10 23007.0\n",
+ "2004 463 David Chen 463 7 39085.0\n",
+ "2005 483 Emma Liu 483 8 34917.0"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def red_rfm_top5(df):\n",
+ " \"\"\"\n",
+ " RFM 分析:找出最有價值的前 5 位客戶\n",
+ "\n",
+ " 計算每位客戶的:\n",
+ " - R (Recency):最近一次下單日期\n",
+ " - F (Frequency):訂單總數\n",
+ " - M (Monetary):消費總金額\n",
+ "\n",
+ " 回傳 DataFrame:\n",
+ " - 欄位:customer_id, customer_name, R, F, M\n",
+ " - 按 M 由大到小排序\n",
+ " - 只取前 5 筆\n",
+ "\n",
+ " 提示:groupby('customer_id').agg(...)\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "import pandas as pd\n",
+ "import time \n",
+ "from datetime import datetime #常與dataframe 搭配使用\n",
+ " #現在時間\n",
+ "now = time.strftime(\"%Y-%m-%d\", time.localtime())\n",
+ "now = datetime.now()\n",
+ "print(now)\n",
+ " #從現在到orderdate的距離\n",
+ "df['date_diff'] = (now-df[\"order_date\"]).dt.days\n",
+ "\n",
+ "#recency : 最近一次下單:取天數最少的\n",
+ "recency = df.groupby(\"customer_id\")[\"date_diff\"].max()\n",
+ "\n",
+ " #frequency : 購買頻率\n",
+ "frequency = df.groupby(\"customer_id\")[\"order_id\"].count()\n",
+ "\n",
+ " #Monetary : 總金額\n",
+ "monetary = df.groupby(\"customer_id\")[\"amount\"].sum() \n",
+ "\n",
+ "names = df.groupby(\"customer_id\")[\"customer_name\"].first()\n",
+ " \n",
+ "\n",
+ "\n",
+ "df_RFM = pd.DataFrame({\n",
+ " 'customer_id':recency,\n",
+ " 'customer_name':names,\n",
+ " 'Recency': recency,\n",
+ " 'Frequency': frequency,\n",
+ " 'Monetary': monetary\n",
+ " })\n",
+ "\n",
+ "df_RFM.head()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e2fbaa41",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ " recency | \n",
+ " frequency | \n",
+ " monetary | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 400 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ " 480 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ " 231 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ " 343 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 253 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 441 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ " 209 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 483 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ " 331 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ " 237 days 23:05:54.249586 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 17 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty recency frequency monetary \n",
+ "0 51 400 days 23:05:54.249586 NaN NaN \n",
+ "1 150 480 days 23:05:54.249586 NaN NaN \n",
+ "2 174 231 days 23:05:54.249586 NaN NaN \n",
+ "3 186 343 days 23:05:54.249586 NaN NaN \n",
+ "4 274 253 days 23:05:54.249586 NaN NaN \n",
+ ".. ... ... ... ... \n",
+ "183 274 441 days 23:05:54.249586 NaN NaN \n",
+ "184 12 209 days 23:05:54.249586 NaN NaN \n",
+ "185 51 483 days 23:05:54.249586 NaN NaN \n",
+ "186 81 331 days 23:05:54.249586 NaN NaN \n",
+ "187 258 237 days 23:05:54.249586 NaN NaN \n",
+ "\n",
+ "[188 rows x 17 columns]"
+ ]
+ },
+ "execution_count": 50,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/homework/m4_timesseries.ipynb b/homework/m4_timesseries.ipynb
new file mode 100644
index 0000000..ddf7bdf
--- /dev/null
+++ b/homework/m4_timesseries.ipynb
@@ -0,0 +1,1114 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3c9278cc",
+ "metadata": {},
+ "source": [
+ "\"\"\"\n",
+ "M4 時間序列與 EDA — 課後作業\n",
+ "==============================\n",
+ "情境:用合併好的訂單資料做時間維度分析,\n",
+ "產出月報級別的商業洞察。\n",
+ "\n",
+ "資料路徑:datasets/ecommerce/orders_enriched.csv\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "042451b9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "1e06f9ed",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def _load_data():\n",
+ " \"\"\"輔助函式:讀取並解析日期\"\"\"\n",
+ " df = pd.read_csv(\"datasets/ecommerce/orders_enriched.csv\",\n",
+ " parse_dates=[\"order_date\"])\n",
+ " return df\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0ca331b5",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟢 送分題(每題 10 分,共 30 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "2c2232f4",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "<>:1: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "<>:1: SyntaxWarning: invalid escape sequence '\\p'\n",
+ "C:\\Users\\highm\\AppData\\Local\\Temp\\ipykernel_6616\\2792110316.py:1: SyntaxWarning: invalid escape sequence '\\p'\n",
+ " df = pd.read_csv(\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_enriched.csv\",\n"
+ ]
+ }
+ ],
+ "source": [
+ "df = pd.read_csv(\"D:\\python_workstation\\iSpan_python-DA-cookbooks\\python-da-homework-2026-main\\python-da-homework-2026-main\\datasets\\ecommerce\\orders_enriched.csv\",\n",
+ " parse_dates=[\"order_date\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "b0893963",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "RangeIndex: 188 entries, 0 to 187\n",
+ "Data columns (total 14 columns):\n",
+ " # Column Non-Null Count Dtype \n",
+ "--- ------ -------------- ----- \n",
+ " 0 order_id 188 non-null int64 \n",
+ " 1 customer_id 188 non-null int64 \n",
+ " 2 product_id 188 non-null int64 \n",
+ " 3 qty 188 non-null float64 \n",
+ " 4 order_date 188 non-null datetime64[us]\n",
+ " 5 amount 188 non-null float64 \n",
+ " 6 customer_name 188 non-null str \n",
+ " 7 region 188 non-null str \n",
+ " 8 signup_date 188 non-null str \n",
+ " 9 vip_level 188 non-null str \n",
+ " 10 product_name 188 non-null str \n",
+ " 11 category 188 non-null str \n",
+ " 12 unit_price 188 non-null int64 \n",
+ " 13 stock_qty 188 non-null int64 \n",
+ "dtypes: datetime64[us](1), float64(2), int64(5), str(6)\n",
+ "memory usage: 20.7 KB\n"
+ ]
+ }
+ ],
+ "source": [
+ "df.info()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "24c10b10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#df.set_index('order_date', inplace=True)\n",
+ "#df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "8f3d7a39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def green_avg_by_month():\n",
+ " \"\"\"\n",
+ " 計算每個月份 (1~12) 的平均訂單金額\n",
+ " 回傳 Series(index=月份 1~12, values=平均金額)\n",
+ " 提示:df['order_date'].dt.month\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "\n",
+ " df['month'] = df['order_date'].dt.month\n",
+ "\n",
+ " monthly_avg = df.groupby('month')['amount'].mean()\n",
+ "\n",
+ " return monthly_avg\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "3d632ea8",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty \n",
+ "0 51 \n",
+ "1 150 \n",
+ "2 174 \n",
+ "3 186 \n",
+ "4 274 \n",
+ ".. ... \n",
+ "183 274 \n",
+ "184 12 \n",
+ "185 51 \n",
+ "186 81 \n",
+ "187 258 \n",
+ "\n",
+ "[188 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "7fc18072",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def green_top3_dates():\n",
+ " \"\"\"\n",
+ " 找出訂單數最多的前 3 個日期\n",
+ " 回傳 Series(index=日期, values=訂單數, 由多到少排序)\n",
+ " 提示:value_counts().head(3)\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " ts['order_id'].resample('D').count().sort_values(ascending =False).head(3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "4ac19c7d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0 2025-03-26\n",
+ "1 2025-01-05\n",
+ "2 2025-09-11\n",
+ "3 2025-05-22\n",
+ "4 2025-08-20\n",
+ " ... \n",
+ "183 2025-02-13\n",
+ "184 2025-10-03\n",
+ "185 2025-01-02\n",
+ "186 2025-06-03\n",
+ "187 2025-09-05\n",
+ "Name: order_date, Length: 188, dtype: datetime64[us]"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def green_date_range():\n",
+ " \"\"\"\n",
+ " 回傳資料的日期範圍 tuple: (最早日期, 最晚日期)\n",
+ " 格式為 pandas Timestamp\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "\n",
+ "df['order_date']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "eca9de71",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty \n",
+ "0 51 \n",
+ "1 150 \n",
+ "2 174 \n",
+ "3 186 \n",
+ "4 274 \n",
+ ".. ... \n",
+ "183 274 \n",
+ "184 12 \n",
+ "185 51 \n",
+ "186 81 \n",
+ "187 258 \n",
+ "\n",
+ "[188 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "583a167a",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟡 核心題(每題 15 分,共 45 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "3693a203",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "order_date\n",
+ "2025-01-31 60062.0\n",
+ "2025-02-28 72367.0\n",
+ "2025-03-31 55920.0\n",
+ "2025-04-30 58506.0\n",
+ "2025-05-31 47879.0\n",
+ "2025-06-30 50901.0\n",
+ "2025-07-31 40796.0\n",
+ "2025-08-31 62706.0\n",
+ "2025-09-30 50745.0\n",
+ "2025-10-31 74376.0\n",
+ "2025-11-30 62533.0\n",
+ "2025-12-31 49597.0\n",
+ "Freq: ME, Name: amount, dtype: float64\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_monthly_revenue():\n",
+ " \"\"\"\n",
+ " 計算每月總營收\n",
+ " 回傳 Series(index=月底日期 period, values=總營收)\n",
+ " 提示:set_index('order_date').resample('ME')['amount'].sum()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "ts = df.set_index('order_date').sort_index()\n",
+ "\n",
+ "monthly = ts['amount'].resample('ME').sum()\n",
+ "print(monthly)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "e3efd8a4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def yellow_rolling_avg(monthly_revenue):\n",
+ " \"\"\"\n",
+ " 計算 3 個月移動平均\n",
+ " 接收 yellow_monthly_revenue() 的結果作為輸入\n",
+ " 回傳 Series(同樣 index,values=移動平均,前 2 筆可為 NaN)\n",
+ " 提示:.rolling(window=3).mean()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " monthly_revenue = yellow_monthly_revenue()\n",
+ " three_months_avg = monthly_revenue.rolling(window=3).mean().head(15)\n",
+ " return three_months_avg\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "id": "888c8800",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "category\n",
+ "Books 4141.909091\n",
+ "Sports 4100.348837\n",
+ "Clothing 3431.820513\n",
+ "Electronics 3233.387097\n",
+ "Home 3024.290323\n",
+ "Name: amount, dtype: float64\n"
+ ]
+ }
+ ],
+ "source": [
+ "#def yellow_category_median(df):\n",
+ "\"\"\"\n",
+ "計算每個商品類別 (category) 的訂單金額中位數,由高到低排序\n",
+ "回傳 Series(index=category, values=中位數)\n",
+ "提示:groupby + median + sort_values\n",
+ "\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "df['month'] = df['order_date'].dt.month\n",
+ "\n",
+ "monthly_avg = df.groupby('category')['amount'].mean().sort_values(ascending =False)\n",
+ "\n",
+ "print(monthly_avg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "176708aa",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🔴 挑戰題(25 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a3837604",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def red_monthly_report():\n",
+ " \"\"\"\n",
+ " 產出月報 DataFrame,每月一列,包含:\n",
+ " - order_count:當月訂單數\n",
+ " - revenue:當月總營收\n",
+ " - active_customers:當月不重複客戶數\n",
+ " - avg_order_value:客單價(revenue / order_count)\n",
+ " - revenue_growth:月營收成長率(相對上月的 % 變化)\n",
+ "\n",
+ " index 為月份 (period 或 datetime)\n",
+ " 提示:resample + agg + pct_change\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "id": "b925fe46",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ " month | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ " 9 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ " 5 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 8 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ "\n",
+ " stock_qty month \n",
+ "0 51 3 \n",
+ "1 150 1 \n",
+ "2 174 9 \n",
+ "3 186 5 \n",
+ "4 274 8 "
+ ]
+ },
+ "execution_count": 29,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.head()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/homework/m5_visualization.ipynb b/homework/m5_visualization.ipynb
new file mode 100644
index 0000000..ced4a3f
--- /dev/null
+++ b/homework/m5_visualization.ipynb
@@ -0,0 +1,1306 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "62f97bb9",
+ "metadata": {},
+ "source": [
+ "\"\"\"\n",
+ "M5 Matplotlib & Seaborn 視覺化 — 課後作業\n",
+ "==========================================\n",
+ "情境:把分析結果做成圖表,用視覺化說故事。\n",
+ "\n",
+ "資料路徑:datasets/ecommerce/orders_enriched.csv\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "cf3332fe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import matplotlib\n",
+ "matplotlib.use(\"Agg\") # 無 GUI 環境也能跑\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd\n",
+ "import seaborn as sns"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "0097f7dd",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "資料形狀: (188, 15)\n"
+ ]
+ }
+ ],
+ "source": [
+ "def _load_data():\n",
+ " \"\"\"輔助函式:讀取資料\"\"\"\n",
+ "plt.rcParams['axes.unicode_minus'] = False\n",
+ "sns.set_theme(style='whitegrid')\n",
+ "\n",
+ "df = pd.read_csv(\n",
+ " '../datasets/ecommerce/orders_enriched.csv',\n",
+ " parse_dates=['order_date'],\n",
+ ")\n",
+ "df['month'] = df['order_date'].dt.to_period('M').astype(str)\n",
+ "print('資料形狀:', df.shape)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0e70527a",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟢 送分題(每題 10 分,共 30 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "be6ddbb6",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ " month | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 2025-03 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ " 2025-01 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ " 2025-09 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ " 2025-05 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 2025-08 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 2025-02 | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ " 2025-10 | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 2025-01 | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ " 2025-06 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ " 2025-09 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 15 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty month \n",
+ "0 51 2025-03 \n",
+ "1 150 2025-01 \n",
+ "2 174 2025-09 \n",
+ "3 186 2025-05 \n",
+ "4 274 2025-08 \n",
+ ".. ... ... \n",
+ "183 274 2025-02 \n",
+ "184 12 2025-10 \n",
+ "185 51 2025-01 \n",
+ "186 81 2025-06 \n",
+ "187 258 2025-09 \n",
+ "\n",
+ "[188 rows x 15 columns]"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "4b4e778c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " category | \n",
+ " amount | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " Books | \n",
+ " 182244.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " Clothing | \n",
+ " 133841.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " Electronics | \n",
+ " 100235.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " Home | \n",
+ " 93753.0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " Sports | \n",
+ " 176315.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " category amount\n",
+ "0 Books 182244.0\n",
+ "1 Clothing 133841.0\n",
+ "2 Electronics 100235.0\n",
+ "3 Home 93753.0\n",
+ "4 Sports 176315.0"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "product_order = df.groupby('category')['amount'].sum().reset_index()\n",
+ "product_order"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "1f913cc3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import matplotlib\n",
+ "matplotlib.use('TkAgg')\n",
+ "import matplotlib.pyplot as plt\n",
+ "#def green_bar_category():\n",
+ "\"\"\"\n",
+ "畫出每個商品類別 (category) 的訂單數長條圖\n",
+ "回傳 matplotlib Figure 物件\n",
+ "提示:sns.countplot 或 value_counts().plot.bar()\n",
+ "\"\"\"\n",
+ "# TODO: 你的程式碼\n",
+ "product_order = df.groupby('category')['stock_qty'].count().reset_index()\n",
+ "fig = plt.figure(figsize=(8, 4)) #開空畫布\n",
+ "sns.countplot(data=df, x='category', palette='viridis', hue='category', legend=False)\n",
+ "plt.title('order count by category')\n",
+ "\n",
+ "\n",
+ "\n",
+ "plt.show()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "f0beaaeb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def green_hist_amount():\n",
+ " \"\"\"\n",
+ " 畫出訂單金額 (amount) 的分佈直方圖,分 20 個 bin\n",
+ " 回傳 matplotlib Figure 物件\n",
+ " 提示:sns.histplot(bins=20) 或 plt.hist()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " pass"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "c2b1f30d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#def green_set_labels():\n",
+ "\"\"\"\n",
+ "建立一個簡單的長條圖(內容不限),但必須設定:\n",
+ "- 圖標題 (title)\n",
+ "- X 軸標籤 (xlabel)\n",
+ "- Y 軸標籤 (ylabel)\n",
+ "回傳 matplotlib Figure 物件\n",
+ "\"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "region_rev = df.groupby('region')['amount'].sum().sort_values(ascending=False).reset_index()\n",
+ "plt.figure(figsize=(8, 4)) #開空畫布\n",
+ "sns.barplot(data=region_rev, x='region', y='amount', palette='viridis', hue='region', legend=False)\n",
+ "plt.title('Revenue by Region', fontweight='bold')\n",
+ "plt.xlabel('Region')\n",
+ "plt.ylabel('Revenue (NT$)')\n",
+ "\n",
+ "# 在柱子上標數字\n",
+ "for i, v in enumerate(region_rev['amount']):\n",
+ " plt.text(i, v, f'{v:,.0f}', ha='center', va='bottom', fontsize=10)\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "535cec10",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟡 核心題(每題 15 分,共 45 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "0f2e6c4c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ " month | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 2025-03 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ " 2025-01 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ " 2025-09 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ " 2025-05 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 2025-08 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 2025-02 | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ " 2025-10 | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 2025-01 | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ " 2025-06 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ " 2025-09 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 15 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty month \n",
+ "0 51 2025-03 \n",
+ "1 150 2025-01 \n",
+ "2 174 2025-09 \n",
+ "3 186 2025-05 \n",
+ "4 274 2025-08 \n",
+ ".. ... ... \n",
+ "183 274 2025-02 \n",
+ "184 12 2025-10 \n",
+ "185 51 2025-01 \n",
+ "186 81 2025-06 \n",
+ "187 258 2025-09 \n",
+ "\n",
+ "[188 rows x 15 columns]"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "370ceb93",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def yellow_line_region_trend():\n",
+ " \"\"\"\n",
+ " 畫折線圖:比較 North 和 South 兩個地區的月營收趨勢\n",
+ " - X 軸:月份\n",
+ " - Y 軸:該月總營收\n",
+ " - 兩條線,有圖例 (legend)\n",
+ " 回傳 matplotlib Figure 物件\n",
+ " 提示:分別 groupby 再 plot,或用 sns.lineplot(hue='region')\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "target_regions = df[df['region'].isin(['North', 'South'])].copy()\n",
+ "target_regions['month'] = target_regions['order_date'].dt.month\n",
+ "\n",
+ "region_rev = target_regions.groupby(['month','region'])['amount'].sum().reset_index()\n",
+ "\n",
+ "plt.figure(figsize=(10, 5))\n",
+ "sns.lineplot(data=region_rev, x='month', y='amount', hue = 'region', marker='o', linewidth=2)\n",
+ "plt.title('Monthly region Trend', fontsize=14, fontweight='bold')\n",
+ "plt.xlabel('Month')\n",
+ "plt.ylabel('total revenue')\n",
+ "plt.xticks(rotation=45)\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "id": "72f9d8bb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def yellow_box_vip():\n",
+ " \"\"\"\n",
+ " 畫箱形圖:比較不同 VIP 等級 (vip_level) 的訂單金額分佈\n",
+ " 回傳 matplotlib Figure 物件\n",
+ " 提示:sns.boxplot(x='vip_level', y='amount', data=df)\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "plt.figure(figsize=(9, 5))\n",
+ "sns.boxplot(data=df, x='vip_level', y='amount', palette='Set2', hue='vip_level', legend=False)\n",
+ "plt.title('Order Amount Distribution by vip level', fontweight='bold')\n",
+ "plt.xlabel('vip_level')\n",
+ "plt.ylabel('Amount')\n",
+ "plt.xticks(rotation=15)\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "id": "a7baffa5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def yellow_scatter_price_amount():\n",
+ " \"\"\"\n",
+ " 畫散佈圖:X=商品單價 (unit_price),Y=訂單金額 (amount)\n",
+ " 回傳 matplotlib Figure 物件\n",
+ " 提示:plt.scatter() 或 sns.scatterplot()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "plt.figure(figsize=(9, 5))\n",
+ "sns.scatterplot(data=df, x='unit_price', y='amount',\n",
+ " hue='category', alpha=0.6, s=60)\n",
+ "plt.title('Unit Price vs Order Amount (by Category)', fontweight='bold')\n",
+ "plt.xlabel('Unit Price')\n",
+ "plt.ylabel('Order Amount')\n",
+ "plt.legend(bbox_to_anchor=(1.02, 1), loc='upper left')\n",
+ "plt.tight_layout()\n",
+ "plt.show() \n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "45fb614c",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🔴 挑戰題(25 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "id": "d7639a54",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def red_category_dashboard(category=\"Electronics\"):\n",
+ " \"\"\"\n",
+ " 針對指定類別,畫 2×2 的 subplot dashboard:\n",
+ " 1. 左上:該類別月營收趨勢 (折線圖)\n",
+ " 2. 右上:該類別各地區營收 (長條圖)\n",
+ " 3. 左下:該類別 Top 5 商品營收 (水平長條圖)\n",
+ " 4. 右下:該類別訂單金額分佈 (直方圖)\n",
+ "\n",
+ " 回傳 matplotlib Figure 物件\n",
+ " 提示:fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "fig, axes = plt.subplots(2, 2, figsize=(16, 9))\n",
+ "fig.suptitle('Electronics Sales Dashboard — 2025', fontsize=16, fontweight='bold')\n",
+ "\n",
+ "# (0,0) 月度趨勢\n",
+ "electronics_df = df[df['category'].str.lower() == 'electronics']\n",
+ "region_electronics_rev = electronics_df.groupby('region')['amount'].sum().reset_index()\n",
+ "plt.figure(figsize=(8, 4)) \n",
+ "sns.lineplot(data=region_electronics_rev, x='region', y='amount', marker='o', ax=axes[0, 0])\n",
+ "plt.title('Electronics Revenue by Region', fontweight='bold')\n",
+ "plt.xlabel('Region')\n",
+ "plt.ylabel('Revenue (NT$)')\n",
+ "\n",
+ "# (0,1) 地區排名\n",
+ "sns.barplot(data=region_electronics_rev, x='region', y='amount', ax=axes[0, 1],\n",
+ " palette='viridis', hue='region', legend=False)\n",
+ "axes[0, 1].set_title('electronics_Revenue by Region')\n",
+ "\n",
+ "# (1,0) 品類分布\n",
+ "\n",
+ "electronics_df = df[df['category'].str.lower() == 'electronics']\n",
+ "product_rev = electronics_df.groupby('product_name')['amount'].sum().reset_index()\n",
+ "top5_products = product_rev.sort_values('amount', ascending=False).head(5)\n",
+ "fig = plt.figure(figsize=(10, 6))\n",
+ "sns.barplot(\n",
+ " data=top5_products, \n",
+ " x='amount', \n",
+ " y='product_name', \n",
+ " hue='product_name', \n",
+ " legend=False\n",
+ " )\n",
+ "\n",
+ "# (1,1) 金額散佈\n",
+ "sns.scatterplot(data=df, x='category', y='amount',\n",
+ " hue='category', alpha=0.6, ax=axes[1, 1], legend=False)\n",
+ "axes[1, 1].set_title('electronics Amount')\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "id": "ac638b9b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ " month | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ " 9 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ " 5 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 8 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ " 10 | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ " 6 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ " 9 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 15 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty month \n",
+ "0 51 3 \n",
+ "1 150 1 \n",
+ "2 174 9 \n",
+ "3 186 5 \n",
+ "4 274 8 \n",
+ ".. ... ... \n",
+ "183 274 2 \n",
+ "184 12 10 \n",
+ "185 51 1 \n",
+ "186 81 6 \n",
+ "187 258 9 \n",
+ "\n",
+ "[188 rows x 15 columns]"
+ ]
+ },
+ "execution_count": 33,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/homework/m6_plotly_capstone.ipynb b/homework/m6_plotly_capstone.ipynb
new file mode 100644
index 0000000..d59d5f2
--- /dev/null
+++ b/homework/m6_plotly_capstone.ipynb
@@ -0,0 +1,5861 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "970659fd",
+ "metadata": {},
+ "source": [
+ "\"\"\"\n",
+ "M6 Plotly 互動儀表板 & Capstone — 課後作業\n",
+ "===========================================\n",
+ "情境:從原始資料到互動式儀表板,完成完整的資料分析 pipeline。\n",
+ "\n",
+ "資料路徑:\n",
+ " - datasets/ecommerce/orders_raw.csv(原始髒資料)\n",
+ " - datasets/ecommerce/customers.csv\n",
+ " - datasets/ecommerce/products.csv\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "4fe2a583",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import plotly.express as px\n",
+ "import plotly.graph_objects as go\n",
+ "from plotly.subplots import make_subplots\n",
+ "import plotly.io as pio\n",
+ "\n",
+ "pio.templates.default = 'plotly_white' # 乾淨白底\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "20a2a92e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "資料形狀: (188, 14)\n"
+ ]
+ }
+ ],
+ "source": [
+ "df = pd.read_csv(\n",
+ " '../datasets/ecommerce/orders_enriched.csv',\n",
+ " parse_dates=['order_date'],\n",
+ ")\n",
+ "print('資料形狀:', df.shape)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b6a4870",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🟢 送分題(每題 10 分,共 30 分)\n",
+ "# ============================================================\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "50d016fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " order_id | \n",
+ " customer_id | \n",
+ " product_id | \n",
+ " qty | \n",
+ " order_date | \n",
+ " amount | \n",
+ " customer_name | \n",
+ " region | \n",
+ " signup_date | \n",
+ " vip_level | \n",
+ " product_name | \n",
+ " category | \n",
+ " unit_price | \n",
+ " stock_qty | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 5064 | \n",
+ " 2022 | \n",
+ " 1026 | \n",
+ " 4.0 | \n",
+ " 2025-03-26 | \n",
+ " 8600.0 | \n",
+ " Victor Lin | \n",
+ " North | \n",
+ " 2023-02-27 | \n",
+ " Gold | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 5023 | \n",
+ " 2026 | \n",
+ " 1021 | \n",
+ " 5.0 | \n",
+ " 2025-01-05 | \n",
+ " 1355.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Throw Pillow | \n",
+ " Home | \n",
+ " 271 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 5123 | \n",
+ " 2013 | \n",
+ " 1013 | \n",
+ " 2.0 | \n",
+ " 2025-09-11 | \n",
+ " 3538.0 | \n",
+ " Mia Huang | \n",
+ " North | \n",
+ " 2023-07-17 | \n",
+ " Platinum | \n",
+ " Cotton T-Shirt | \n",
+ " Clothing | \n",
+ " 1769 | \n",
+ " 174 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5118 | \n",
+ " 2005 | \n",
+ " 1028 | \n",
+ " 1.0 | \n",
+ " 2025-05-22 | \n",
+ " 1618.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Water Bottle | \n",
+ " Sports | \n",
+ " 1618 | \n",
+ " 186 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 5161 | \n",
+ " 2017 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-08-20 | \n",
+ " 1846.0 | \n",
+ " Quinn Chen | \n",
+ " East | \n",
+ " 2023-08-11 | \n",
+ " Silver | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 183 | \n",
+ " 5094 | \n",
+ " 2026 | \n",
+ " 1019 | \n",
+ " 3.0 | \n",
+ " 2025-02-13 | \n",
+ " 5538.0 | \n",
+ " Zoe Huang | \n",
+ " South | \n",
+ " 2023-05-16 | \n",
+ " Platinum | \n",
+ " Coffee Mug | \n",
+ " Home | \n",
+ " 1846 | \n",
+ " 274 | \n",
+ "
\n",
+ " \n",
+ " | 184 | \n",
+ " 5041 | \n",
+ " 2014 | \n",
+ " 1001 | \n",
+ " 5.0 | \n",
+ " 2025-10-03 | \n",
+ " 8135.0 | \n",
+ " Nick Huang | \n",
+ " West | \n",
+ " 2023-09-28 | \n",
+ " Gold | \n",
+ " Wireless Mouse | \n",
+ " Electronics | \n",
+ " 1627 | \n",
+ " 12 | \n",
+ "
\n",
+ " \n",
+ " | 185 | \n",
+ " 5157 | \n",
+ " 2005 | \n",
+ " 1026 | \n",
+ " 5.0 | \n",
+ " 2025-01-02 | \n",
+ " 10750.0 | \n",
+ " Emma Liu | \n",
+ " West | \n",
+ " 2023-05-18 | \n",
+ " Bronze | \n",
+ " Dumbbell 5kg | \n",
+ " Sports | \n",
+ " 2150 | \n",
+ " 51 | \n",
+ "
\n",
+ " \n",
+ " | 186 | \n",
+ " 5134 | \n",
+ " 2015 | \n",
+ " 1012 | \n",
+ " 5.0 | \n",
+ " 2025-06-03 | \n",
+ " 9580.0 | \n",
+ " Olivia Huang | \n",
+ " North | \n",
+ " 2023-12-15 | \n",
+ " Bronze | \n",
+ " Clean Code | \n",
+ " Books | \n",
+ " 1916 | \n",
+ " 81 | \n",
+ "
\n",
+ " \n",
+ " | 187 | \n",
+ " 5135 | \n",
+ " 2010 | \n",
+ " 1007 | \n",
+ " 4.0 | \n",
+ " 2025-09-05 | \n",
+ " 2436.0 | \n",
+ " Jack Liu | \n",
+ " South | \n",
+ " 2023-03-12 | \n",
+ " Platinum | \n",
+ " Python Cookbook | \n",
+ " Books | \n",
+ " 609 | \n",
+ " 258 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
188 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty \n",
+ "0 51 \n",
+ "1 150 \n",
+ "2 174 \n",
+ "3 186 \n",
+ "4 274 \n",
+ ".. ... \n",
+ "183 274 \n",
+ "184 12 \n",
+ "185 51 \n",
+ "186 81 \n",
+ "187 258 \n",
+ "\n",
+ "[188 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d9db8c45",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.plotly.v1+json": {
+ "config": {
+ "plotlyServerURL": "https://plot.ly"
+ },
+ "data": [
+ {
+ "hovertemplate": "category=%{x}
amount=%{text}",
+ "legendgroup": "Books",
+ "marker": {
+ "color": "#636efa",
+ "pattern": {
+ "shape": ""
+ }
+ },
+ "name": "Books",
+ "orientation": "v",
+ "showlegend": true,
+ "text": {
+ "bdata": "AAAAACA/BkE=",
+ "dtype": "f8"
+ },
+ "textposition": "outside",
+ "texttemplate": "%{text:,.0f}",
+ "type": "bar",
+ "x": [
+ "Books"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAACA/BkE=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "hovertemplate": "category=%{x}
amount=%{text}",
+ "legendgroup": "Sports",
+ "marker": {
+ "color": "#EF553B",
+ "pattern": {
+ "shape": ""
+ }
+ },
+ "name": "Sports",
+ "orientation": "v",
+ "showlegend": true,
+ "text": {
+ "bdata": "AAAAANiFBUE=",
+ "dtype": "f8"
+ },
+ "textposition": "outside",
+ "texttemplate": "%{text:,.0f}",
+ "type": "bar",
+ "x": [
+ "Sports"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAANiFBUE=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "hovertemplate": "category=%{x}
amount=%{text}",
+ "legendgroup": "Clothing",
+ "marker": {
+ "color": "#00cc96",
+ "pattern": {
+ "shape": ""
+ }
+ },
+ "name": "Clothing",
+ "orientation": "v",
+ "showlegend": true,
+ "text": {
+ "bdata": "AAAAAIhWAEE=",
+ "dtype": "f8"
+ },
+ "textposition": "outside",
+ "texttemplate": "%{text:,.0f}",
+ "type": "bar",
+ "x": [
+ "Clothing"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAIhWAEE=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "hovertemplate": "category=%{x}
amount=%{text}",
+ "legendgroup": "Electronics",
+ "marker": {
+ "color": "#ab63fa",
+ "pattern": {
+ "shape": ""
+ }
+ },
+ "name": "Electronics",
+ "orientation": "v",
+ "showlegend": true,
+ "text": {
+ "bdata": "AAAAALB4+EA=",
+ "dtype": "f8"
+ },
+ "textposition": "outside",
+ "texttemplate": "%{text:,.0f}",
+ "type": "bar",
+ "x": [
+ "Electronics"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAALB4+EA=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "hovertemplate": "category=%{x}
amount=%{text}",
+ "legendgroup": "Home",
+ "marker": {
+ "color": "#FFA15A",
+ "pattern": {
+ "shape": ""
+ }
+ },
+ "name": "Home",
+ "orientation": "v",
+ "showlegend": true,
+ "text": {
+ "bdata": "AAAAAJDj9kA=",
+ "dtype": "f8"
+ },
+ "textposition": "outside",
+ "texttemplate": "%{text:,.0f}",
+ "type": "bar",
+ "x": [
+ "Home"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAJDj9kA=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ }
+ ],
+ "layout": {
+ "barmode": "relative",
+ "height": 400,
+ "legend": {
+ "title": {
+ "text": "category"
+ },
+ "tracegroupgap": 0
+ },
+ "showlegend": false,
+ "template": {
+ "data": {
+ "bar": [
+ {
+ "error_x": {
+ "color": "#2a3f5f"
+ },
+ "error_y": {
+ "color": "#2a3f5f"
+ },
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "baxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "type": "carpet"
+ }
+ ],
+ "choropleth": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "choropleth"
+ }
+ ],
+ "contour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "contour"
+ }
+ ],
+ "contourcarpet": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "contourcarpet"
+ }
+ ],
+ "heatmap": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmap"
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "histogram2d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2d"
+ }
+ ],
+ "histogram2dcontour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2dcontour"
+ }
+ ],
+ "mesh3d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "mesh3d"
+ }
+ ],
+ "parcoords": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "parcoords"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ],
+ "scatter": [
+ {
+ "fillpattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ },
+ "type": "scatter"
+ }
+ ],
+ "scatter3d": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatter3d"
+ }
+ ],
+ "scattercarpet": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattercarpet"
+ }
+ ],
+ "scattergeo": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergeo"
+ }
+ ],
+ "scattergl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergl"
+ }
+ ],
+ "scattermap": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermap"
+ }
+ ],
+ "scattermapbox": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermapbox"
+ }
+ ],
+ "scatterpolar": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolar"
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolargl"
+ }
+ ],
+ "scatterternary": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterternary"
+ }
+ ],
+ "surface": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "surface"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#EBF0F8"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#C8D4E3"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "type": "table"
+ }
+ ]
+ },
+ "layout": {
+ "annotationdefaults": {
+ "arrowcolor": "#2a3f5f",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "autotypenumbers": "strict",
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ],
+ "sequential": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ]
+ },
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#2a3f5f"
+ },
+ "geo": {
+ "bgcolor": "white",
+ "lakecolor": "white",
+ "landcolor": "white",
+ "showlakes": true,
+ "showland": true,
+ "subunitcolor": "#C8D4E3"
+ },
+ "hoverlabel": {
+ "align": "left"
+ },
+ "hovermode": "closest",
+ "mapbox": {
+ "style": "light"
+ },
+ "paper_bgcolor": "white",
+ "plot_bgcolor": "white",
+ "polar": {
+ "angularaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "radialaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "yaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "zaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#2a3f5f"
+ }
+ },
+ "ternary": {
+ "aaxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "caxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ }
+ },
+ "title": {
+ "x": 0.05
+ },
+ "xaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ }
+ }
+ },
+ "title": {
+ "text": "Revenue by category"
+ },
+ "xaxis": {
+ "anchor": "y",
+ "categoryarray": [
+ "Books",
+ "Sports",
+ "Clothing",
+ "Electronics",
+ "Home"
+ ],
+ "categoryorder": "array",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "category"
+ }
+ },
+ "yaxis": {
+ "anchor": "x",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "amount"
+ }
+ }
+ }
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "def green_plotly_bar():\n",
+ " \"\"\"\n",
+ " 用 Plotly Express 畫出每個商品類別 (category) 的總營收長條圖\n",
+ " 資料來源:orders_enriched.csv\n",
+ " 回傳 plotly Figure 物件\n",
+ " 提示:px.bar()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "\n",
+ "category_rev = df.groupby('category', as_index=False)['amount'].sum().sort_values('amount', ascending=False)\n",
+ "fig = px.bar(category_rev, x='category', y='amount', text='amount',\n",
+ " color='category', title='Revenue by category')\n",
+ "fig.update_traces(texttemplate='%{text:,.0f}', textposition='outside')\n",
+ "fig.update_layout(height=400, showlegend=False)\n",
+ "fig.show()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "00af9c96",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.plotly.v1+json": {
+ "config": {
+ "plotlyServerURL": "https://plot.ly"
+ },
+ "data": [
+ {
+ "hovertemplate": "month=%{x}
amount=%{y}",
+ "legendgroup": "",
+ "line": {
+ "color": "#636efa",
+ "dash": "solid"
+ },
+ "marker": {
+ "symbol": "circle"
+ },
+ "mode": "lines+markers",
+ "name": "",
+ "orientation": "v",
+ "showlegend": false,
+ "type": "scatter",
+ "x": [
+ "2025-01",
+ "2025-02",
+ "2025-03",
+ "2025-04",
+ "2025-05",
+ "2025-06",
+ "2025-07",
+ "2025-08",
+ "2025-09",
+ "2025-10",
+ "2025-11",
+ "2025-12"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAMBT7UAAAAAA8KrxQAAAAAAATutAAAAAAECR7EAAAAAA4GDnQAAAAACg2uhAAAAAAIDr40AAAAAAQJ7uQAAAAAAgx+hAAAAAAIAo8kAAAAAAoIjuQAAAAACgN+hA",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ }
+ ],
+ "layout": {
+ "height": 400,
+ "legend": {
+ "tracegroupgap": 0
+ },
+ "template": {
+ "data": {
+ "bar": [
+ {
+ "error_x": {
+ "color": "#2a3f5f"
+ },
+ "error_y": {
+ "color": "#2a3f5f"
+ },
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "baxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "type": "carpet"
+ }
+ ],
+ "choropleth": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "choropleth"
+ }
+ ],
+ "contour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "contour"
+ }
+ ],
+ "contourcarpet": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "contourcarpet"
+ }
+ ],
+ "heatmap": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmap"
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "histogram2d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2d"
+ }
+ ],
+ "histogram2dcontour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2dcontour"
+ }
+ ],
+ "mesh3d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "mesh3d"
+ }
+ ],
+ "parcoords": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "parcoords"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ],
+ "scatter": [
+ {
+ "fillpattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ },
+ "type": "scatter"
+ }
+ ],
+ "scatter3d": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatter3d"
+ }
+ ],
+ "scattercarpet": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattercarpet"
+ }
+ ],
+ "scattergeo": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergeo"
+ }
+ ],
+ "scattergl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergl"
+ }
+ ],
+ "scattermap": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermap"
+ }
+ ],
+ "scattermapbox": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermapbox"
+ }
+ ],
+ "scatterpolar": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolar"
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolargl"
+ }
+ ],
+ "scatterternary": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterternary"
+ }
+ ],
+ "surface": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "surface"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#EBF0F8"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#C8D4E3"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "type": "table"
+ }
+ ]
+ },
+ "layout": {
+ "annotationdefaults": {
+ "arrowcolor": "#2a3f5f",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "autotypenumbers": "strict",
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ],
+ "sequential": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ]
+ },
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#2a3f5f"
+ },
+ "geo": {
+ "bgcolor": "white",
+ "lakecolor": "white",
+ "landcolor": "white",
+ "showlakes": true,
+ "showland": true,
+ "subunitcolor": "#C8D4E3"
+ },
+ "hoverlabel": {
+ "align": "left"
+ },
+ "hovermode": "closest",
+ "mapbox": {
+ "style": "light"
+ },
+ "paper_bgcolor": "white",
+ "plot_bgcolor": "white",
+ "polar": {
+ "angularaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "radialaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "yaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "zaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#2a3f5f"
+ }
+ },
+ "ternary": {
+ "aaxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "caxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ }
+ },
+ "title": {
+ "x": 0.05
+ },
+ "xaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ }
+ }
+ },
+ "title": {
+ "text": "Monthly Revenue Trend"
+ },
+ "xaxis": {
+ "anchor": "y",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "month"
+ }
+ },
+ "yaxis": {
+ "anchor": "x",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "amount"
+ }
+ }
+ }
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "def green_plotly_line():\n",
+ " \"\"\"\n",
+ " 用 Plotly Express 畫出月營收趨勢折線圖\n",
+ " 資料來源:orders_enriched.csv\n",
+ " 回傳 plotly Figure 物件\n",
+ " 提示:先 groupby 月份算總營收,再 px.line()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ " \n",
+ "\n",
+ "df['month'] = df['order_date'].dt.to_period('M').astype(str)\n",
+ "monthly = df.groupby('month', as_index=False)['amount'].sum()\n",
+ "\n",
+ "fig = px.line(monthly, x='month', y='amount', markers=True,\n",
+ " title='Monthly Revenue Trend')\n",
+ "fig.update_layout(height=400)\n",
+ "fig.show()\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "1a34822f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.plotly.v1+json": {
+ "config": {
+ "plotlyServerURL": "https://plot.ly"
+ },
+ "data": [
+ {
+ "domain": {
+ "x": [
+ 0,
+ 1
+ ],
+ "y": [
+ 0,
+ 1
+ ]
+ },
+ "hole": 0.4,
+ "hovertemplate": "vip_level=%{label}
qty=%{value}",
+ "labels": [
+ "Bronze",
+ "Gold",
+ "Platinum",
+ "Silver"
+ ],
+ "legendgroup": "",
+ "name": "",
+ "showlegend": true,
+ "type": "pie",
+ "values": {
+ "bdata": "AAAAAABAXUAAAAAAAGBuQAAAAAAAYGNAAAAAAAAATkA=",
+ "dtype": "f8"
+ }
+ }
+ ],
+ "layout": {
+ "height": 400,
+ "legend": {
+ "tracegroupgap": 0
+ },
+ "template": {
+ "data": {
+ "bar": [
+ {
+ "error_x": {
+ "color": "#2a3f5f"
+ },
+ "error_y": {
+ "color": "#2a3f5f"
+ },
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "baxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "type": "carpet"
+ }
+ ],
+ "choropleth": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "choropleth"
+ }
+ ],
+ "contour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "contour"
+ }
+ ],
+ "contourcarpet": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "contourcarpet"
+ }
+ ],
+ "heatmap": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmap"
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "histogram2d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2d"
+ }
+ ],
+ "histogram2dcontour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2dcontour"
+ }
+ ],
+ "mesh3d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "mesh3d"
+ }
+ ],
+ "parcoords": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "parcoords"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ],
+ "scatter": [
+ {
+ "fillpattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ },
+ "type": "scatter"
+ }
+ ],
+ "scatter3d": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatter3d"
+ }
+ ],
+ "scattercarpet": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattercarpet"
+ }
+ ],
+ "scattergeo": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergeo"
+ }
+ ],
+ "scattergl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergl"
+ }
+ ],
+ "scattermap": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermap"
+ }
+ ],
+ "scattermapbox": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermapbox"
+ }
+ ],
+ "scatterpolar": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolar"
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolargl"
+ }
+ ],
+ "scatterternary": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterternary"
+ }
+ ],
+ "surface": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "surface"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#EBF0F8"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#C8D4E3"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "type": "table"
+ }
+ ]
+ },
+ "layout": {
+ "annotationdefaults": {
+ "arrowcolor": "#2a3f5f",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "autotypenumbers": "strict",
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ],
+ "sequential": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ]
+ },
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#2a3f5f"
+ },
+ "geo": {
+ "bgcolor": "white",
+ "lakecolor": "white",
+ "landcolor": "white",
+ "showlakes": true,
+ "showland": true,
+ "subunitcolor": "#C8D4E3"
+ },
+ "hoverlabel": {
+ "align": "left"
+ },
+ "hovermode": "closest",
+ "mapbox": {
+ "style": "light"
+ },
+ "paper_bgcolor": "white",
+ "plot_bgcolor": "white",
+ "polar": {
+ "angularaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "radialaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "yaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "zaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#2a3f5f"
+ }
+ },
+ "ternary": {
+ "aaxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "caxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ }
+ },
+ "title": {
+ "x": 0.05
+ },
+ "xaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ }
+ }
+ },
+ "title": {
+ "text": "VIP Level qty"
+ }
+ }
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "def green_plotly_pie():\n",
+ " \"\"\"\n",
+ " 用 Plotly Express 畫出 VIP 等級 (vip_level) 的訂單數佔比圓餅圖\n",
+ " 資料來源:orders_enriched.csv\n",
+ " 回傳 plotly Figure 物件\n",
+ " 提示:px.pie()\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "vip_qty = df.groupby('vip_level', as_index=False)['qty'].sum()\n",
+ "fig = px.pie(vip_qty, names='vip_level', values='qty',\n",
+ " title='VIP Level qty', hole=0.4) # hole=0.4 變成 donut\n",
+ "fig.update_layout(height=400)\n",
+ "fig.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0b33c70b",
+ "metadata": {},
+ "source": [
+ "\n",
+ "# ============================================================\n",
+ "# 🟡 核心題(每題 15 分,共 45 分)\n",
+ "# ============================================================\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "7a7f2541",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "清理完成:188 筆訂單\n",
+ "合併後形狀: (188, 14)\n",
+ "欄位數: 14\n",
+ " order_id customer_id product_id qty order_date amount customer_name \\\n",
+ "0 5064 2022 1026 4.0 2025-03-26 8600.0 Victor Lin \n",
+ "1 5023 2026 1021 5.0 2025-01-05 1355.0 Zoe Huang \n",
+ "2 5123 2013 1013 2.0 2025-09-11 3538.0 Mia Huang \n",
+ "3 5118 2005 1028 1.0 2025-05-22 1618.0 Emma Liu \n",
+ "4 5161 2017 1019 3.0 2025-08-20 1846.0 Quinn Chen \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "183 5094 2026 1019 3.0 2025-02-13 5538.0 Zoe Huang \n",
+ "184 5041 2014 1001 5.0 2025-10-03 8135.0 Nick Huang \n",
+ "185 5157 2005 1026 5.0 2025-01-02 10750.0 Emma Liu \n",
+ "186 5134 2015 1012 5.0 2025-06-03 9580.0 Olivia Huang \n",
+ "187 5135 2010 1007 4.0 2025-09-05 2436.0 Jack Liu \n",
+ "\n",
+ " region signup_date vip_level product_name category unit_price \\\n",
+ "0 North 2023-02-27 Gold Dumbbell 5kg Sports 2150 \n",
+ "1 South 2023-05-16 Platinum Throw Pillow Home 271 \n",
+ "2 North 2023-07-17 Platinum Cotton T-Shirt Clothing 1769 \n",
+ "3 West 2023-05-18 Bronze Water Bottle Sports 1618 \n",
+ "4 East 2023-08-11 Silver Coffee Mug Home 1846 \n",
+ ".. ... ... ... ... ... ... \n",
+ "183 South 2023-05-16 Platinum Coffee Mug Home 1846 \n",
+ "184 West 2023-09-28 Gold Wireless Mouse Electronics 1627 \n",
+ "185 West 2023-05-18 Bronze Dumbbell 5kg Sports 2150 \n",
+ "186 North 2023-12-15 Bronze Clean Code Books 1916 \n",
+ "187 South 2023-03-12 Platinum Python Cookbook Books 609 \n",
+ "\n",
+ " stock_qty \n",
+ "0 51 \n",
+ "1 150 \n",
+ "2 174 \n",
+ "3 186 \n",
+ "4 274 \n",
+ ".. ... \n",
+ "183 274 \n",
+ "184 12 \n",
+ "185 51 \n",
+ "186 81 \n",
+ "187 258 \n",
+ "\n",
+ "[188 rows x 14 columns]\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_clean_and_merge(orders_raw, customers, products):\n",
+ " \"\"\"\n",
+ " 完整 ETL:從髒資料到合併完成的 DataFrame\n",
+ " 1. 讀取 orders_raw.csv 並清理(欄位名稱、金額、日期、缺值、去重)\n",
+ " 2. 合併 customers.csv 和 products.csv\n",
+ " 回傳:合併後的 DataFrame\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "def clean_orders(orders_raw):\n",
+ " df = pd.read_csv('../datasets/ecommerce/orders_raw.csv')\n",
+ " df.columns = df.columns.str.strip().str.lower()\n",
+ " df['amount'] = (\n",
+ " df['amount'].astype(str)\n",
+ " .str.replace('$','', regex=False)\n",
+ " .str.replace(',','', regex=False)\n",
+ " .astype(float)\n",
+ " )\n",
+ " df['order_date'] = pd.to_datetime(df['order_date'], errors='coerce')\n",
+ " df = df.dropna(subset=['order_date'])\n",
+ " df['qty'] = df['qty'].fillna(df['qty'].median())\n",
+ " df = df.drop_duplicates()\n",
+ " return df\n",
+ "\n",
+ "raw_orders = pd.read_csv('../datasets/ecommerce/orders_raw.csv')\n",
+ "orders = clean_orders(raw_orders)\n",
+ "print(f'清理完成:{orders.shape[0]} 筆訂單')\n",
+ "orders.head(3)\n",
+ "\n",
+ "customers = pd.read_csv('../datasets/ecommerce/customers.csv')\n",
+ "products = pd.read_csv('../datasets/ecommerce/products.csv')\n",
+ "\n",
+ "enriched = (\n",
+ " orders\n",
+ " .merge(customers, on='customer_id', how='left')\n",
+ " .merge(products, on='product_id', how='left')\n",
+ ")\n",
+ "print(f'合併後形狀: {enriched.shape}')\n",
+ "print(f'欄位數: {len(enriched.columns)}')\n",
+ "\n",
+ "print(enriched)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "cd6063dc",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "總營收: 686,388\n",
+ "總訂單數: 188\n",
+ "活躍顧客數: 26\n",
+ "客單價: 3,651\n"
+ ]
+ }
+ ],
+ "source": [
+ "def yellow_kpi_summary(df):\n",
+ " \"\"\"\n",
+ " 計算 4 個核心 KPI,回傳 dict:\n",
+ " {\n",
+ " \"total_revenue\": float, # 總營收\n",
+ " \"order_count\": int, # 訂單數\n",
+ " \"active_customers\": int, # 不重複客戶數\n",
+ " \"avg_order_value\": float, # 平均客單價\n",
+ " }\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "\n",
+ "enriched['month'] = enriched['order_date'].dt.to_period('M').astype(str)\n",
+ "kpis = {\n",
+ " '總營收': enriched['amount'].sum(),\n",
+ " '總訂單數': len(enriched),\n",
+ " '活躍顧客數': enriched['customer_id'].nunique(),\n",
+ " '客單價': enriched['amount'].sum() / len(enriched),\n",
+ "}\n",
+ "for k, v in kpis.items():\n",
+ " print(f'{k}: {v:>12,.0f}')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "bd60d953",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.plotly.v1+json": {
+ "config": {
+ "plotlyServerURL": "https://plot.ly"
+ },
+ "data": [
+ {
+ "customdata": [
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Running Shoes"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Running Shoes"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Resistance Band"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Running Shoes"
+ ],
+ [
+ "Running Shoes"
+ ],
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Resistance Band"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Yoga Mat"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Yoga Mat"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Running Shoes"
+ ],
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Jump Rope"
+ ],
+ [
+ "Running Shoes"
+ ],
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Yoga Mat"
+ ],
+ [
+ "Yoga Mat"
+ ],
+ [
+ "Dumbbell 5kg"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Resistance Band"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Yoga Mat"
+ ],
+ [
+ "Resistance Band"
+ ],
+ [
+ "Water Bottle"
+ ],
+ [
+ "Dumbbell 5kg"
+ ]
+ ],
+ "hovertemplate": "category=Sports
unit_price=%{x}
amount=%{y}
product_name=%{customdata[0]}",
+ "legendgroup": "Sports",
+ "marker": {
+ "color": "#636efa",
+ "symbol": "circle"
+ },
+ "mode": "markers",
+ "name": "Sports",
+ "orientation": "v",
+ "showlegend": true,
+ "type": "scatter",
+ "x": {
+ "bdata": "ZghSBugD2gHaAVIGZgjoA9oBZghLAlIG6APoA2YIUgZSBlIGUgbaAdoBUgZLAtoBnwdSBp8HUgboA2YI2gHoA2YInwefB2YIUgZLAlIGnwdLAlIGZgg=",
+ "dtype": "i2"
+ },
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAADMwEAAAAAAAEiZQAAAAAAAQI9AAAAAAACgjUAAAAAAAKCdQAAAAAAASKlAAAAAAAD/xEAAAAAAAHCnQAAAAAAAoH1AAAAAAADMsEAAAAAAAO6mQAAAAAAASJlAAAAAAABAn0AAAAAAAHCnQAAAAAAAzLBAAAAAAABIuUAAAAAAAEi5QAAAAAAASLlAAAAAAABIuUAAAAAAAISiQAAAAAAAoH1AAAAAAABImUAAAAAAAFiCQAAAAAAAOJZAAAAAAAB8nkAAAAAAAEiZQAAAAACADcNAAAAAAABImUAAAAAAAIizQAAAAAAAzLBAAAAAAACgjUAAAAAAAIizQAAAAAAAzLBAAAAAAAB8vkAAAAAAAN22QAAAAAAAMrlAAAAAAABIqUAAAAAAAO6mQAAAAAAASLlAAAAAAADdtkAAAAAAAFiiQAAAAAAAmr9AAAAAAAD/xEA=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "customdata": [
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Coffee Mug"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Desk Lamp"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Coffee Mug"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Desk Lamp"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Wall Clock"
+ ],
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Desk Lamp"
+ ],
+ [
+ "Coffee Mug"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Candle Set"
+ ],
+ [
+ "Throw Pillow"
+ ],
+ [
+ "Coffee Mug"
+ ],
+ [
+ "Plant Pot"
+ ],
+ [
+ "Coffee Mug"
+ ]
+ ],
+ "hovertemplate": "category=Home
unit_price=%{x}
amount=%{y}
product_name=%{customdata[0]}",
+ "legendgroup": "Home",
+ "marker": {
+ "color": "#EF553B",
+ "symbol": "circle"
+ },
+ "mode": "markers",
+ "name": "Home",
+ "orientation": "v",
+ "showlegend": true,
+ "type": "scatter",
+ "x": {
+ "bdata": "DwE2BycIDwF+AScIJwi/AA8BNge/AH4BJwi/ACcIxQUPAScIDwEnCA8BfgE2B78AvwC/ACcIDwE2B78ANgc=",
+ "dtype": "i2"
+ },
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAAAslUAAAAAAANicQAAAAAAATsBAAAAAAADwkEAAAAAAANidQAAAAAAATqBAAAAAAAB1uEAAAAAAAOiBQAAAAAAA8JBAAAAAAAAHwkAAAAAAAOCHQAAAAAAA4IdAAAAAAIBhxEAAAAAAAOCHQAAAAAAATqBAAAAAAABPsUAAAAAAAPCQQAAAAAAATqBAAAAAAAAslUAAAAAAAE6wQAAAAAAAaIlAAAAAAADgd0AAAAAAAAfCQAAAAAAA4GdAAAAAAADogUAAAAAAANiNQAAAAAAATsBAAAAAAADwcEAAAAAAAKK1QAAAAAAA4GdAAAAAAACitUA=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "customdata": [
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Cap"
+ ],
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Sneakers"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Sneakers"
+ ],
+ [
+ "Denim Jeans"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Scarf"
+ ],
+ [
+ "Sneakers"
+ ],
+ [
+ "Sneakers"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Denim Jeans"
+ ],
+ [
+ "Denim Jeans"
+ ],
+ [
+ "Denim Jeans"
+ ],
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Cap"
+ ],
+ [
+ "Cap"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Cap"
+ ],
+ [
+ "Sneakers"
+ ],
+ [
+ "Cap"
+ ],
+ [
+ "Cap"
+ ],
+ [
+ "Denim Jeans"
+ ],
+ [
+ "Hoodie"
+ ],
+ [
+ "Sneakers"
+ ],
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Denim Jeans"
+ ],
+ [
+ "Scarf"
+ ],
+ [
+ "Cotton T-Shirt"
+ ],
+ [
+ "Scarf"
+ ],
+ [
+ "Sneakers"
+ ]
+ ],
+ "hovertemplate": "category=Clothing
unit_price=%{x}
amount=%{y}
product_name=%{customdata[0]}",
+ "legendgroup": "Clothing",
+ "marker": {
+ "color": "#00cc96",
+ "symbol": "circle"
+ },
+ "mode": "markers",
+ "name": "Clothing",
+ "orientation": "v",
+ "showlegend": true,
+ "type": "scatter",
+ "x": {
+ "bdata": "6QY6AekGXAlHAVwJRwHwAlwJXAlcCVwJXAnpBgUGRwFHAVwJ8ALwAvAC6QY6AToBXAnpBjoBRwE6AToB8AJcCUcB6QbwAgUG6QYFBkcB",
+ "dtype": "i2"
+ },
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAACkq0AAAAAAAHCNQAAAAAAApKtAAAAAAAC4wkAAAAAAAHCEQAAAAAAAuLJAAAAAAACojkAAAAAAAGCtQAAAAAAAuKJAAAAAAAAUvEAAAAAAABS8QAAAAAAAuKJAAAAAAABmx0AAAAAAAKS7QAAAAAAAFKhAAAAAAABwhEAAAAAAAHCUQAAAAAAAuKJAAAAAAACAp0AAAAAAAICnQAAAAAAAgIdAAAAAAACkm0AAAAAAAIiYQAAAAAAAoHNAAAAAAAAUvEAAAAAAAKS7QAAAAAAAiJhAAAAAAACMmUAAAAAAAKCTQAAAAAAAoHNAAAAAAACAl0AAAAAAALiyQAAAAAAAcIRAAAAAAACku0AAAAAAAICnQAAAAAAAFKhAAAAAAACku0AAAAAAABSoQAAAAAAAcIRA",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "customdata": [
+ [
+ "ML Primer"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Statistics 101"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "Python Cookbook"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "Statistics 101"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Python Cookbook"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Python Cookbook"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Statistics 101"
+ ],
+ [
+ "SQL Guide"
+ ],
+ [
+ "SQL Guide"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "SQL Guide"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Statistics 101"
+ ],
+ [
+ "Statistics 101"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "SQL Guide"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "ML Primer"
+ ],
+ [
+ "Statistics 101"
+ ],
+ [
+ "Python Cookbook"
+ ],
+ [
+ "Data Science Handbook"
+ ],
+ [
+ "Clean Code"
+ ],
+ [
+ "Python Cookbook"
+ ]
+ ],
+ "hovertemplate": "category=Books
unit_price=%{x}
amount=%{y}
product_name=%{customdata[0]}",
+ "legendgroup": "Books",
+ "marker": {
+ "color": "#ab63fa",
+ "symbol": "circle"
+ },
+ "mode": "markers",
+ "name": "Books",
+ "orientation": "v",
+ "showlegend": true,
+ "type": "scatter",
+ "x": {
+ "bdata": "RwQBBkcEfAcBBuIFRwRhAnwHAQZHBHwHAQZHBEcE4gV8B2ECAQZhAgEG4gUxAjECAQYBBgEGRwR8BzECfAfiBeIFAQYxAgEGfAd8B0cE4gVhAgEGfAdhAg==",
+ "dtype": "i2"
+ },
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAAAcsUAAAAAAAAS4QAAAAAAAY7VAAAAAAADwnUAAAAAAAAS4QAAAAAAAiJdAAAAAAAAcsUAAAAAAAAijQAAAAAAAdLZAAAAAAAAEuEAAAAAAAGO1QAAAAAAAtsJAAAAAAAAEqEAAAAAAAByhQAAAAAAAHKFAAAAAAACIp0AAAAAAAPC9QAAAAAAACKNAAAAAAAAEmEAAAAAAAIycQAAAAAAABJhAAAAAAACIt0AAAAAAAEyaQAAAAAAA6qVAAAAAAAADskAAAAAAAASYQAAAAAAABJhAAAAAAACqqUAAAAAAAPCdQAAAAAAATJpAAAAAAADwvUAAAAAAAGq9QAAAAAAAiJdAAAAAAAADskAAAAAAAIiRQAAAAAAABLhAAAAAAAB0tkAAAAAAALbCQAAAAAAAY7VAAAAAAACmsUAAAAAAAIycQAAAAAAAA7JAAAAAAAC2wkAAAAAAAAijQA==",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "customdata": [
+ [
+ "Webcam HD"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "USB-C Cable"
+ ],
+ [
+ "Webcam HD"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "Webcam HD"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "USB-C Cable"
+ ],
+ [
+ "Bluetooth Speaker"
+ ],
+ [
+ "Laptop Stand"
+ ],
+ [
+ "Webcam HD"
+ ],
+ [
+ "USB-C Cable"
+ ],
+ [
+ "Webcam HD"
+ ],
+ [
+ "Wireless Mouse"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "Laptop Stand"
+ ],
+ [
+ "Bluetooth Speaker"
+ ],
+ [
+ "Webcam HD"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "Webcam HD"
+ ],
+ [
+ "Laptop Stand"
+ ],
+ [
+ "Power Bank"
+ ],
+ [
+ "USB-C Cable"
+ ],
+ [
+ "USB-C Cable"
+ ],
+ [
+ "Wireless Mouse"
+ ],
+ [
+ "USB-C Cable"
+ ],
+ [
+ "Bluetooth Speaker"
+ ],
+ [
+ "Wireless Mouse"
+ ]
+ ],
+ "hovertemplate": "category=Electronics
unit_price=%{x}
amount=%{y}
product_name=%{customdata[0]}",
+ "legendgroup": "Electronics",
+ "marker": {
+ "color": "#FFA15A",
+ "symbol": "circle"
+ },
+ "mode": "markers",
+ "name": "Electronics",
+ "orientation": "v",
+ "showlegend": true,
+ "type": "scatter",
+ "x": {
+ "bdata": "tgadAFMHtgadAJ0AtgadAJ0AnQBTB2wCIgG2BlMHtgZbBp0AIgFsArYGnQC2BiIBnQBTB1MHWwZTB2wCWwY=",
+ "dtype": "i2"
+ },
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAAAitEAAAAAAAKCDQAAAAACAT8JAAAAAAADYukAAAAAAAHB9QAAAAAAAcH1AAAAAAADYqkAAAAAAAHB9QAAAAAAAoINAAAAAAACgY0AAAAAAgE/CQAAAAAAAOKhAAAAAAAAgckAAAAAAANiaQAAAAAAA+bVAAAAAAADYukAAAAAAAMe/QAAAAAAAoINAAAAAAAAwi0AAAAAAABCdQAAAAAAA2JpAAAAAAACgY0AAAAAAANiqQAAAAAAAMItAAAAAAACIiEAAAAAAAEydQAAAAAAA+bVAAAAAAABsuUAAAAAAAEytQAAAAAAAYJNAAAAAAADHv0A=",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ }
+ ],
+ "layout": {
+ "height": 450,
+ "legend": {
+ "title": {
+ "text": "category"
+ },
+ "tracegroupgap": 0
+ },
+ "template": {
+ "data": {
+ "bar": [
+ {
+ "error_x": {
+ "color": "#2a3f5f"
+ },
+ "error_y": {
+ "color": "#2a3f5f"
+ },
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "baxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "type": "carpet"
+ }
+ ],
+ "choropleth": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "choropleth"
+ }
+ ],
+ "contour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "contour"
+ }
+ ],
+ "contourcarpet": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "contourcarpet"
+ }
+ ],
+ "heatmap": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmap"
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "histogram2d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2d"
+ }
+ ],
+ "histogram2dcontour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2dcontour"
+ }
+ ],
+ "mesh3d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "mesh3d"
+ }
+ ],
+ "parcoords": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "parcoords"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ],
+ "scatter": [
+ {
+ "fillpattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ },
+ "type": "scatter"
+ }
+ ],
+ "scatter3d": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatter3d"
+ }
+ ],
+ "scattercarpet": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattercarpet"
+ }
+ ],
+ "scattergeo": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergeo"
+ }
+ ],
+ "scattergl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergl"
+ }
+ ],
+ "scattermap": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermap"
+ }
+ ],
+ "scattermapbox": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermapbox"
+ }
+ ],
+ "scatterpolar": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolar"
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolargl"
+ }
+ ],
+ "scatterternary": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterternary"
+ }
+ ],
+ "surface": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "surface"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#EBF0F8"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#C8D4E3"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "type": "table"
+ }
+ ]
+ },
+ "layout": {
+ "annotationdefaults": {
+ "arrowcolor": "#2a3f5f",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "autotypenumbers": "strict",
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ],
+ "sequential": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ]
+ },
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#2a3f5f"
+ },
+ "geo": {
+ "bgcolor": "white",
+ "lakecolor": "white",
+ "landcolor": "white",
+ "showlakes": true,
+ "showland": true,
+ "subunitcolor": "#C8D4E3"
+ },
+ "hoverlabel": {
+ "align": "left"
+ },
+ "hovermode": "closest",
+ "mapbox": {
+ "style": "light"
+ },
+ "paper_bgcolor": "white",
+ "plot_bgcolor": "white",
+ "polar": {
+ "angularaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "radialaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "yaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "zaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#2a3f5f"
+ }
+ },
+ "ternary": {
+ "aaxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "caxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ }
+ },
+ "title": {
+ "x": 0.05
+ },
+ "xaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ }
+ }
+ },
+ "title": {
+ "text": "Unit Price"
+ },
+ "xaxis": {
+ "anchor": "y",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "unit_price"
+ }
+ },
+ "yaxis": {
+ "anchor": "x",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "amount"
+ }
+ }
+ }
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "def yellow_plotly_scatter(df):\n",
+ " \"\"\"\n",
+ " 用 Plotly Express 畫互動散佈圖:\n",
+ " - X:商品單價 (unit_price)\n",
+ " - Y:訂單金額 (amount)\n",
+ " - 顏色:商品類別 (category)\n",
+ " - hover 顯示:商品名稱 (product_name)\n",
+ " 回傳 plotly Figure 物件\n",
+ " 提示:px.scatter(hover_data=['product_name'])\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "fig = px.scatter(df, x='unit_price', y='amount',\n",
+ " color='category', hover_data=['product_name'],\n",
+ " title='Unit Price')\n",
+ "fig.update_layout(height=450)\n",
+ "fig.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6268ef65",
+ "metadata": {},
+ "source": [
+ "# ============================================================\n",
+ "# 🔴 挑戰題(25 分)\n",
+ "# ============================================================"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "d7d0e155",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "c:\\Users\\highm\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\plotly\\graph_objs\\_deprecations.py:378: DeprecationWarning: plotly.graph_objs.Line is deprecated.\n",
+ "Please replace it with one of the following more specific types\n",
+ " - plotly.graph_objs.scatter.Line\n",
+ " - plotly.graph_objs.layout.shape.Line\n",
+ " - etc.\n",
+ "\n",
+ " warnings.warn(\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.plotly.v1+json": {
+ "config": {
+ "plotlyServerURL": "https://plot.ly"
+ },
+ "data": [
+ {
+ "mode": "lines+markers",
+ "name": "Monthly",
+ "type": "scatter",
+ "x": [
+ "2025-01",
+ "2025-02",
+ "2025-03",
+ "2025-04",
+ "2025-05",
+ "2025-06",
+ "2025-07",
+ "2025-08",
+ "2025-09",
+ "2025-10",
+ "2025-11",
+ "2025-12"
+ ],
+ "xaxis": "x",
+ "y": {
+ "bdata": "AAAAAMBT7UAAAAAA8KrxQAAAAAAATutAAAAAAECR7EAAAAAA4GDnQAAAAACg2uhAAAAAAIDr40AAAAAAQJ7uQAAAAAAgx+hAAAAAAIAo8kAAAAAAoIjuQAAAAACgN+hA",
+ "dtype": "f8"
+ },
+ "yaxis": "y"
+ },
+ {
+ "name": "Top Products",
+ "type": "bar",
+ "x": [
+ "Hoodie",
+ "Clean Code",
+ "Water Bottle",
+ "Dumbbell 5kg",
+ "Data Science Handbook",
+ "Candle Set",
+ "Cotton T-Shirt",
+ "USB-C Cable",
+ "ML Primer",
+ "Coffee Mug"
+ ],
+ "xaxis": "x2",
+ "y": {
+ "bdata": "AAAAAIA/7UAAAAAAgADtQAAAAACA3OpAAAAAAMA+6kAAAAAA4EPnQAAAAABgZuVAAAAAAKAj4kAAAAAAIGXhQAAAAABACuBAAAAAAICl3kA=",
+ "dtype": "f8"
+ },
+ "yaxis": "y2"
+ },
+ {
+ "name": "Region",
+ "type": "bar",
+ "x": [
+ "East",
+ "North",
+ "South",
+ "West"
+ ],
+ "xaxis": "x3",
+ "y": {
+ "bdata": "AAAAAADs6UAAAAAAiJIOQQAAAABsoxBBAAAAAIDq+kA=",
+ "dtype": "f8"
+ },
+ "yaxis": "y3"
+ },
+ {
+ "domain": {
+ "x": [
+ 0.55,
+ 1
+ ],
+ "y": [
+ 0,
+ 0.375
+ ]
+ },
+ "hole": 0.4,
+ "labels": [
+ "Books",
+ "Clothing",
+ "Electronics",
+ "Home",
+ "Sports"
+ ],
+ "name": "Category",
+ "type": "pie",
+ "values": {
+ "bdata": "AAAAACA/BkEAAAAAiFYAQQAAAACwePhAAAAAAJDj9kAAAAAA2IUFQQ==",
+ "dtype": "f8"
+ }
+ }
+ ],
+ "layout": {
+ "annotations": [
+ {
+ "font": {
+ "size": 16
+ },
+ "showarrow": false,
+ "text": "Monthly Revenue Trend",
+ "x": 0.225,
+ "xanchor": "center",
+ "xref": "paper",
+ "y": 1,
+ "yanchor": "bottom",
+ "yref": "paper"
+ },
+ {
+ "font": {
+ "size": 16
+ },
+ "showarrow": false,
+ "text": "Top 10 Products",
+ "x": 0.775,
+ "xanchor": "center",
+ "xref": "paper",
+ "y": 1,
+ "yanchor": "bottom",
+ "yref": "paper"
+ },
+ {
+ "font": {
+ "size": 16
+ },
+ "showarrow": false,
+ "text": "Revenue by Region",
+ "x": 0.225,
+ "xanchor": "center",
+ "xref": "paper",
+ "y": 0.375,
+ "yanchor": "bottom",
+ "yref": "paper"
+ },
+ {
+ "font": {
+ "size": 16
+ },
+ "showarrow": false,
+ "text": "Category Share",
+ "x": 0.775,
+ "xanchor": "center",
+ "xref": "paper",
+ "y": 0.375,
+ "yanchor": "bottom",
+ "yref": "paper"
+ }
+ ],
+ "height": 750,
+ "showlegend": false,
+ "template": {
+ "data": {
+ "bar": [
+ {
+ "error_x": {
+ "color": "#2a3f5f"
+ },
+ "error_y": {
+ "color": "#2a3f5f"
+ },
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "white",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "baxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "#C8D4E3",
+ "linecolor": "#C8D4E3",
+ "minorgridcolor": "#C8D4E3",
+ "startlinecolor": "#2a3f5f"
+ },
+ "type": "carpet"
+ }
+ ],
+ "choropleth": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "choropleth"
+ }
+ ],
+ "contour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "contour"
+ }
+ ],
+ "contourcarpet": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "contourcarpet"
+ }
+ ],
+ "heatmap": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmap"
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "histogram2d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2d"
+ }
+ ],
+ "histogram2dcontour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2dcontour"
+ }
+ ],
+ "mesh3d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "mesh3d"
+ }
+ ],
+ "parcoords": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "parcoords"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ],
+ "scatter": [
+ {
+ "fillpattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ },
+ "type": "scatter"
+ }
+ ],
+ "scatter3d": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatter3d"
+ }
+ ],
+ "scattercarpet": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattercarpet"
+ }
+ ],
+ "scattergeo": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergeo"
+ }
+ ],
+ "scattergl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergl"
+ }
+ ],
+ "scattermap": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermap"
+ }
+ ],
+ "scattermapbox": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermapbox"
+ }
+ ],
+ "scatterpolar": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolar"
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolargl"
+ }
+ ],
+ "scatterternary": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterternary"
+ }
+ ],
+ "surface": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "surface"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#EBF0F8"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#C8D4E3"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "type": "table"
+ }
+ ]
+ },
+ "layout": {
+ "annotationdefaults": {
+ "arrowcolor": "#2a3f5f",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "autotypenumbers": "strict",
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ],
+ "sequential": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ]
+ },
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#2a3f5f"
+ },
+ "geo": {
+ "bgcolor": "white",
+ "lakecolor": "white",
+ "landcolor": "white",
+ "showlakes": true,
+ "showland": true,
+ "subunitcolor": "#C8D4E3"
+ },
+ "hoverlabel": {
+ "align": "left"
+ },
+ "hovermode": "closest",
+ "mapbox": {
+ "style": "light"
+ },
+ "paper_bgcolor": "white",
+ "plot_bgcolor": "white",
+ "polar": {
+ "angularaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "radialaxis": {
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": ""
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "yaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ },
+ "zaxis": {
+ "backgroundcolor": "white",
+ "gridcolor": "#DFE8F3",
+ "gridwidth": 2,
+ "linecolor": "#EBF0F8",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#EBF0F8"
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#2a3f5f"
+ }
+ },
+ "ternary": {
+ "aaxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ },
+ "bgcolor": "white",
+ "caxis": {
+ "gridcolor": "#DFE8F3",
+ "linecolor": "#A2B1C6",
+ "ticks": ""
+ }
+ },
+ "title": {
+ "x": 0.05
+ },
+ "xaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "automargin": true,
+ "gridcolor": "#EBF0F8",
+ "linecolor": "#EBF0F8",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#EBF0F8",
+ "zerolinewidth": 2
+ }
+ }
+ },
+ "title": {
+ "text": "E-Commerce Sales Dashboard — 2025"
+ },
+ "xaxis": {
+ "anchor": "y",
+ "domain": [
+ 0,
+ 0.45
+ ]
+ },
+ "xaxis2": {
+ "anchor": "y2",
+ "domain": [
+ 0.55,
+ 1
+ ],
+ "tickangle": 45
+ },
+ "xaxis3": {
+ "anchor": "y3",
+ "domain": [
+ 0,
+ 0.45
+ ]
+ },
+ "yaxis": {
+ "anchor": "x",
+ "domain": [
+ 0.625,
+ 1
+ ]
+ },
+ "yaxis2": {
+ "anchor": "x2",
+ "domain": [
+ 0.625,
+ 1
+ ]
+ },
+ "yaxis3": {
+ "anchor": "x3",
+ "domain": [
+ 0,
+ 0.375
+ ]
+ }
+ }
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "def red_dashboard():\n",
+ " \"\"\"\n",
+ " Capstone:完整的互動式儀表板\n",
+ "\n",
+ " 流程:\n",
+ " 1. 清理 orders_raw.csv + 合併三張表\n",
+ " 2. 建立 2×2 subplot dashboard(用 plotly make_subplots):\n",
+ " - 左上:月營收趨勢 (line)\n",
+ " - 右上:Top 10 商品營收 (bar)\n",
+ " - 左下:各地區營收 (bar)\n",
+ " - 右下:類別營收佔比 (pie/donut)\n",
+ " 3. 設定整體標題\n",
+ "\n",
+ " 回傳 plotly Figure 物件\n",
+ " 提示:from plotly.subplots import make_subplots\n",
+ " \"\"\"\n",
+ " # TODO: 你的程式碼\n",
+ "monthly = enriched.groupby('month', as_index=False)['amount'].sum()\n",
+ "top_prod = (enriched.groupby('product_name', as_index=False)['amount']\n",
+ " .sum().sort_values('amount', ascending=False).head(10))\n",
+ "region_rev = enriched.groupby('region', as_index=False)['amount'].sum()\n",
+ "cat_rev = enriched.groupby('category', as_index=False)['amount'].sum()\n",
+ "\n",
+ "fig = make_subplots(\n",
+ " rows=2, cols=2,\n",
+ " subplot_titles=('Monthly Revenue Trend',\n",
+ " 'Top 10 Products',\n",
+ " 'Revenue by Region',\n",
+ " 'Category Share'),\n",
+ " specs=[[{'type':'xy'}, {'type':'xy'}],\n",
+ " [{'type':'xy'}, {'type':'domain'}]],\n",
+ ")\n",
+ "\n",
+ "fig.add_trace(go.Line(x=monthly['month'], y=monthly['amount'],\n",
+ " mode='lines+markers', name='Monthly'), row=1, col=1)\n",
+ "fig.add_trace(go.Bar(x=top_prod['product_name'], y=top_prod['amount'],\n",
+ " name='Top Products'), row=1, col=2)\n",
+ "fig.add_trace(go.Bar(x=region_rev['region'], y=region_rev['amount'],\n",
+ " name='Region'), row=2, col=1)\n",
+ "fig.add_trace(go.Pie(labels=cat_rev['category'], values=cat_rev['amount'],\n",
+ " name='Category', hole=0.4), row=2, col=2)\n",
+ "\n",
+ "fig.update_layout(\n",
+ " title_text='E-Commerce Sales Dashboard — 2025',\n",
+ " height=750, showlegend=False,\n",
+ ")\n",
+ "fig.update_xaxes(tickangle=45, row=1, col=2)\n",
+ "fig.show()\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}