Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions grading_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# 📊 作業批改結果

**總分:600 / 600(100%)— 等級 A**

---

## M1 NumPy(100/100 — 100%)

| 題目 | 分數 | 狀態 |
|:-----|:----:|:----:|
| `test_green_mean` | 10/10 | ✅ |
| `test_green_double` | 10/10 | ✅ |
| `test_green_filter` | 10/10 | ✅ |
| `test_yellow_expensive_count` | 15/15 | ✅ |
| `test_yellow_top3_stock_indices` | 15/15 | ✅ |
| `test_yellow_restock_cost` | 15/15 | ✅ |
| `test_red_double11_prices` | 20/20 | ✅ |
| `test_red_no_forloop` | 5/5 | ✅ |

> ⚠️ 解答模組未找到

---

## M2 Pandas 清理(100/100 — 100%)

| 題目 | 分數 | 狀態 |
|:-----|:----:|:----:|
| `test_green_read_csv` | 10/10 | ✅ |
| `test_green_shape` | 10/10 | ✅ |
| `test_green_dtypes` | 10/10 | ✅ |
| `test_yellow_clean_columns` | 15/15 | ✅ |
| `test_yellow_clean_amount` | 15/15 | ✅ |
| `test_yellow_drop_duplicates` | 15/15 | ✅ |
| `test_red_clean_orders_returns_df` | 4/4 | ✅ |
| `test_red_clean_orders_columns` | 4/4 | ✅ |
| `test_red_clean_orders_amount_is_numeric` | 4/4 | ✅ |
| `test_red_clean_orders_date_is_datetime` | 5/5 | ✅ |
| `test_red_clean_orders_no_nulls` | 4/4 | ✅ |
| `test_red_clean_orders_no_duplicates` | 4/4 | ✅ |

> ⚠️ 解答模組未找到

---

## M3 Pandas 進階(100/100 — 100%)

| 題目 | 分數 | 狀態 |
|:-----|:----:|:----:|
| `test_green_load_and_merge` | 10/10 | ✅ |
| `test_green_row_count` | 10/10 | ✅ |
| `test_green_column_list` | 10/10 | ✅ |
| `test_yellow_top_category` | 15/15 | ✅ |
| `test_yellow_gold_vip_stats` | 15/15 | ✅ |
| `test_yellow_region_avg_amount` | 15/15 | ✅ |
| `test_red_rfm_top5_shape` | 9/9 | ✅ |
| `test_red_rfm_top5_columns` | 8/8 | ✅ |
| `test_red_rfm_top5_sorted_by_m` | 8/8 | ✅ |

> ⚠️ 解答模組未找到

---

## M4 時間序列(100/100 — 100%)

| 題目 | 分數 | 狀態 |
|:-----|:----:|:----:|
| `test_green_avg_by_month` | 10/10 | ✅ |
| `test_green_top3_dates` | 10/10 | ✅ |
| `test_green_date_range` | 10/10 | ✅ |
| `test_yellow_monthly_revenue` | 15/15 | ✅ |
| `test_yellow_rolling_avg` | 15/15 | ✅ |
| `test_yellow_category_median` | 15/15 | ✅ |
| `test_red_monthly_report_columns` | 9/9 | ✅ |
| `test_red_monthly_report_values` | 8/8 | ✅ |
| `test_red_monthly_report_growth` | 8/8 | ✅ |

> ⚠️ 解答模組未找到

---

## M5 視覺化(100/100 — 100%)

| 題目 | 分數 | 狀態 |
|:-----|:----:|:----:|
| `test_green_bar_category` | 10/10 | ✅ |
| `test_green_hist_amount` | 10/10 | ✅ |
| `test_green_set_labels` | 10/10 | ✅ |
| `test_yellow_line_region_trend` | 15/15 | ✅ |
| `test_yellow_box_vip` | 15/15 | ✅ |
| `test_yellow_scatter_price_amount` | 15/15 | ✅ |
| `test_red_category_dashboard_is_figure` | 13/13 | ✅ |
| `test_red_category_dashboard_has_4_subplots` | 12/12 | ✅ |

> ⚠️ 解答模組未找到

---

## M6 Plotly Capstone(100/100 — 100%)

| 題目 | 分數 | 狀態 |
|:-----|:----:|:----:|
| `test_green_plotly_bar` | 10/10 | ✅ |
| `test_green_plotly_line` | 10/10 | ✅ |
| `test_green_plotly_pie` | 10/10 | ✅ |
| `test_yellow_clean_and_merge` | 15/15 | ✅ |
| `test_yellow_kpi_summary` | 15/15 | ✅ |
| `test_yellow_plotly_scatter` | 15/15 | ✅ |
| `test_red_dashboard_is_figure` | 13/13 | ✅ |
| `test_red_dashboard_has_traces` | 12/12 | ✅ |

> ⚠️ 解答模組未找到
29 changes: 14 additions & 15 deletions homework/m1_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,19 @@

def green_mean():
"""建立 [10, 20, 30, 40, 50],回傳所有元素的平均值 (float)"""
# TODO: 你的程式碼
pass

arr = np.array([10,20,30,40,50])
return float(arr.mean())

def green_double():
"""建立 [10, 20, 30, 40, 50],回傳所有元素乘以 2 的 ndarray"""
# TODO: 你的程式碼
pass
arr = np.array([10,20,30,40,50])
return arr * 2


def green_filter():
"""建立 [10, 20, 30, 40, 50],回傳大於 25 的元素 (ndarray)"""
# TODO: 你的程式碼
pass
arr = np.array([10,20,30,40,50])
return arr[arr > 25]


# ============================================================
Expand All @@ -41,26 +40,26 @@ def green_filter():

def yellow_expensive_count(prices):
"""回傳單價 > 1000 的商品數量 (int)"""
# TODO: 你的程式碼
pass
mask = prices > 1000
return mask.sum()


def yellow_top3_stock_indices(stocks):
"""
回傳庫存最多的前 3 個商品的索引位置 (ndarray, 由大到小排)
提示:np.argsort
"""
# TODO: 你的程式碼
pass
idx = np.argsort(-stocks)
return idx[0:3]


def yellow_restock_cost(prices, stocks):
"""
單價 < 500 的商品,每種各進貨 50 個,回傳總花費 (float/int)
提示:布林遮罩 + .sum()
"""
# TODO: 你的程式碼
pass
total = prices[prices < 500] *50
return total.sum()


# ============================================================
Expand All @@ -76,5 +75,5 @@ def red_double11_prices(prices, stocks):
回傳每個商品的雙 11 售價 (ndarray)
提示:np.where 可以巢狀使用
"""
# TODO: 你的程式碼
pass
return np.where(stocks >= 100, prices * 0.7,
np.where(stocks >= 20, prices * 0.9, prices))
32 changes: 18 additions & 14 deletions homework/m2_pandas_cleaning.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,23 @@ def green_read_csv():
讀取 orders_raw.csv,回傳原始 DataFrame(不做任何清理)
提示:pd.read_csv()
"""
# TODO: 你的程式碼
pass
return pd.read_csv('datasets/ecommerce/orders_raw.csv')


def green_shape(df):
"""
回傳 DataFrame 的 (列數, 欄數) tuple
提示:df.shape
"""
# TODO: 你的程式碼
pass
return df.shape


def green_dtypes(df):
"""
回傳 DataFrame 的欄位型別 (Series)
提示:df.dtypes
"""
# TODO: 你的程式碼
pass
return df.dtypes


# ============================================================
Expand All @@ -51,8 +48,9 @@ def yellow_clean_columns(df):
回傳清理後的 DataFrame(不要修改原始 df)
提示:df.columns.str.strip().str.lower()
"""
# TODO: 你的程式碼
pass
df2 = df.copy()
df2.columns = df2.columns.str.strip().str.lower()
return df2


def yellow_clean_amount(df):
Expand All @@ -62,17 +60,18 @@ def yellow_clean_amount(df):
回傳清理後的 DataFrame(不要修改原始 df)
提示:.str.replace() + .astype(float)
"""
# TODO: 你的程式碼
pass
df2 = df.copy()
df2['amount'] = df2['amount'].astype(str).str.replace('$','', regex=False).str.replace(',','', regex=False).astype(float)
return df2


def yellow_drop_duplicates(df):
"""
移除完全重複的列,回傳去重後的 DataFrame
提示:df.drop_duplicates()
"""
# TODO: 你的程式碼
pass
df = df.drop_duplicates()
return df


# ============================================================
Expand All @@ -92,5 +91,10 @@ def red_clean_orders(path):
回傳:清理後的 DataFrame
提示:pd.to_datetime(errors='coerce')
"""
# TODO: 你的程式碼
pass
df = pd.read_csv(path)
df.columns = df.columns.str.strip().str.lower()
df['amount'] = df['amount'].astype(str).str.replace('$','',regex=False).str.replace(',','',regex=False).astype(float)
df['order_date'] = pd.to_datetime(df['order_date'], errors='coerce')
df = df.dropna(subset=['order_date','amount']) # 只要這兩個欄位中任一個有缺失值,該列就會被剔除。
df = df.drop_duplicates()
return df
40 changes: 25 additions & 15 deletions homework/m3_pandas_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,25 @@ def green_load_and_merge():
- 再 LEFT JOIN products.csv ON product_id
提示:pd.merge(how='left')
"""
# TODO: 你的程式碼
pass
orders = pd.read_csv('datasets/ecommerce/orders_clean.csv')
customers = pd.read_csv('datasets/ecommerce/customers.csv')
products = pd.read_csv('datasets/ecommerce/products.csv')
df=(
orders
.merge(customers,on='customer_id',how='left')
.merge(products,on='product_id',how='left')
)
return df


def green_row_count(df):
"""回傳 DataFrame 的列數 (int)"""
# TODO: 你的程式碼
pass
return df.shape[0]


def green_column_list(df):
"""回傳 DataFrame 的所有欄位名稱 (list)"""
# TODO: 你的程式碼
pass
return list(df.columns)


# ============================================================
Expand All @@ -49,28 +54,26 @@ def yellow_top_category(df):
回傳該類別名稱 (str)
提示:groupby('category')['amount'].sum()
"""
# TODO: 你的程式碼
pass

top = df.groupby('category')['amount'].sum().sort_values(ascending=False)
return f'{top.idxmax()}'

def yellow_gold_vip_stats(df):
"""
Gold VIP 客戶總共下了幾張訂單?總金額多少?
回傳 tuple: (訂單數 int, 總金額 float)
提示:df[df['vip_level'] == 'Gold']
"""
# TODO: 你的程式碼
pass

gold_mask = df[df['vip_level'] == 'Gold']
gold = gold_mask['amount'].agg(['count', 'sum'])
return (int(gold['count']), float(gold['sum']))

def yellow_region_avg_amount(df):
"""
計算每個地區 (region) 的平均訂單金額
回傳 Series(index=region, values=平均金額)
提示:groupby('region')['amount'].mean()
"""
# TODO: 你的程式碼
pass
return df.groupby('region')['amount'].mean()


# ============================================================
Expand All @@ -94,4 +97,11 @@ def red_rfm_top5(df):
提示:groupby('customer_id').agg(...)
"""
# TODO: 你的程式碼
pass
rfm = df.groupby('customer_id').agg(
R=('order_date', 'max'),
F=('order_id', 'count'),
M=('amount', 'sum'),
customer_name=("customer_name", "first")
).reset_index()
result = rfm.sort_values('M',ascending=False).head()
return result[["customer_id", "customer_name", "R", "F", "M"]]
Loading
Loading