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
42 changes: 31 additions & 11 deletions homework/m2_pandas_cleaning.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ def green_read_csv():
提示:pd.read_csv()
"""
# TODO: 你的程式碼
pass

def green_read_csv():
return pd.read_csv("datasets/ecommerce/orders_raw.csv")

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


def green_dtypes(df):
Expand All @@ -38,7 +39,8 @@ def green_dtypes(df):
提示:df.dtypes
"""
# TODO: 你的程式碼
pass
def green_dtypes(df):
return df.dtypes


# ============================================================
Expand All @@ -52,8 +54,9 @@ def yellow_clean_columns(df):
提示:df.columns.str.strip().str.lower()
"""
# TODO: 你的程式碼
pass

new_df = df.copy()
new_df.columns = new_df.columns.str.strip().str.lower()
return new_df

def yellow_clean_amount(df):
"""
Expand All @@ -63,17 +66,22 @@ def yellow_clean_amount(df):
提示:.str.replace() + .astype(float)
"""
# TODO: 你的程式碼
pass

new_df = df.copy()
new_df["amount"] = (
new_df["amount"]
.str.replace("$", "", regex=False)
.str.replace(",", "", regex=False)
.astype(float)
)
return new_df

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

return df.drop_duplicates()

# ============================================================
# 🔴 挑戰題(25 分)
Expand All @@ -93,4 +101,16 @@ def red_clean_orders(path):
提示:pd.to_datetime(errors='coerce')
"""
# TODO: 你的程式碼
pass
df = pd.read_csv(path)
df.columns = df.columns.str.strip().str.lower()
df["amount"] = (
df["amount"]
.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=["amount", "order_date"])
df = df.drop_duplicates()

return df
38 changes: 31 additions & 7 deletions homework/m3_pandas_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,26 @@ def green_load_and_merge():
提示: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 = pd.merge(orders, customers, on="customer_id", how="left")
df = pd.merge(df, products, on="product_id", how="left")

return df


def green_row_count(df):
"""回傳 DataFrame 的列數 (int)"""
# TODO: 你的程式碼
pass
return len(df)


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


# ============================================================
Expand All @@ -50,7 +57,7 @@ def yellow_top_category(df):
提示:groupby('category')['amount'].sum()
"""
# TODO: 你的程式碼
pass
return df.groupby("category")["amount"].sum().idxmax()


def yellow_gold_vip_stats(df):
Expand All @@ -60,7 +67,10 @@ def yellow_gold_vip_stats(df):
提示:df[df['vip_level'] == 'Gold']
"""
# TODO: 你的程式碼
pass
gold_df = df[df["vip_level"] == "Gold"]
order_count = len(gold_df)
total_amount = gold_df["amount"].sum()
return (order_count, total_amount)


def yellow_region_avg_amount(df):
Expand All @@ -70,7 +80,7 @@ def yellow_region_avg_amount(df):
提示:groupby('region')['amount'].mean()
"""
# TODO: 你的程式碼
pass
return df.groupby("region")["amount"].mean()


# ============================================================
Expand All @@ -94,4 +104,18 @@ def red_rfm_top5(df):
提示:groupby('customer_id').agg(...)
"""
# TODO: 你的程式碼
pass
df = df.copy()
df["order_date"] = pd.to_datetime(df["order_date"], errors="coerce")

rfm = df.groupby("customer_id").agg(
R=("order_date", "max"),
F=("order_id", "count"),
M=("amount", "sum")
).reset_index()

names = df[["customer_id", "customer_name"]].drop_duplicates()
rfm = pd.merge(rfm, names, on="customer_id", how="left")
rfm = rfm.sort_values(by="M", ascending=False).head(5)
rfm = rfm[["customer_id", "customer_name", "R", "F", "M"]]

return rfm
22 changes: 15 additions & 7 deletions homework/m4_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def green_avg_by_month():
提示:df['order_date'].dt.month
"""
# TODO: 你的程式碼
pass
df = _load_data()
return df.groupby(df["order_date"].dt.month)["amount"].mean()


def green_top3_dates():
Expand All @@ -37,7 +38,8 @@ def green_top3_dates():
提示:value_counts().head(3)
"""
# TODO: 你的程式碼
pass
df = _load_data()
return df["order_date"].dt.date.value_counts().head(3)


def green_date_range():
Expand All @@ -46,7 +48,8 @@ def green_date_range():
格式為 pandas Timestamp
"""
# TODO: 你的程式碼
pass
df = _load_data()
return (df["order_date"].min(), df["order_date"].max())


# ============================================================
Expand All @@ -60,7 +63,8 @@ def yellow_monthly_revenue():
提示:set_index('order_date').resample('ME')['amount'].sum()
"""
# TODO: 你的程式碼
pass
df = _load_data()
return df.set_index("order_date").resample("ME")["amount"].sum()


def yellow_rolling_avg(monthly_revenue):
Expand All @@ -71,7 +75,7 @@ def yellow_rolling_avg(monthly_revenue):
提示:.rolling(window=3).mean()
"""
# TODO: 你的程式碼
pass
return monthly_revenue.rolling(window=3).mean()


def yellow_category_median(df):
Expand All @@ -81,7 +85,11 @@ def yellow_category_median(df):
提示:groupby + median + sort_values
"""
# TODO: 你的程式碼
pass
return (
df.groupby("category")["amount"]
.median()
.sort_values(ascending=False)
)


# ============================================================
Expand All @@ -101,4 +109,4 @@ def red_monthly_report():
提示:resample + agg + pct_change
"""
# TODO: 你的程式碼
pass

45 changes: 36 additions & 9 deletions homework/m5_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import pandas as pd
import seaborn as sns


def _load_data():
"""輔助函式:讀取資料"""
return pd.read_csv("datasets/ecommerce/orders_enriched.csv",
Expand All @@ -29,7 +28,10 @@ def green_bar_category():
提示:sns.countplot 或 value_counts().plot.bar()
"""
# TODO: 你的程式碼
pass
df = _load_data()
fig, ax = plt.subplots()
sns.countplot(x="category", data=df, ax=ax)
return fig


def green_hist_amount():
Expand All @@ -39,7 +41,10 @@ def green_hist_amount():
提示:sns.histplot(bins=20) 或 plt.hist()
"""
# TODO: 你的程式碼
pass
df = _load_data()
fig, ax = plt.subplots()
sns.histplot(df["amount"], bins=20, ax=ax)
return fig


def green_set_labels():
Expand All @@ -51,8 +56,12 @@ def green_set_labels():
回傳 matplotlib Figure 物件
"""
# TODO: 你的程式碼
pass

fig, ax = plt.subplots()
ax.bar(["A", "B", "C"], [10, 20, 15])
ax.set_title("Sample Bar Chart")
ax.set_xlabel("Category")
ax.set_ylabel("Value")
return fig

# ============================================================
# 🟡 核心題(每題 15 分,共 45 分)
Expand All @@ -68,7 +77,20 @@ def yellow_line_region_trend():
提示:分別 groupby 再 plot,或用 sns.lineplot(hue='region')
"""
# TODO: 你的程式碼
pass
df = _load_data()

monthly = (
df.set_index("order_date")
.groupby("region")
.resample("ME")["amount"]
.sum()
.reset_index()
)
monthly = monthly[monthly["region"].isin(["North", "South"])]
fig, ax = plt.subplots()
sns.lineplot(data=monthly, x="order_date", y="amount",
hue="region", ax=ax)
return fig


def yellow_box_vip():
Expand All @@ -78,7 +100,10 @@ def yellow_box_vip():
提示:sns.boxplot(x='vip_level', y='amount', data=df)
"""
# TODO: 你的程式碼
pass
df = _load_data()
fig, ax = plt.subplots()
sns.boxplot(x="vip_level", y="amount", data=df, ax=ax)
return fig


def yellow_scatter_price_amount():
Expand All @@ -88,7 +113,10 @@ def yellow_scatter_price_amount():
提示:plt.scatter() 或 sns.scatterplot()
"""
# TODO: 你的程式碼
pass
df = _load_data()
fig, ax = plt.subplots()
sns.scatterplot(x="unit_price", y="amount", data=df, ax=ax)
return fig


# ============================================================
Expand All @@ -107,4 +135,3 @@ def red_category_dashboard(category="Electronics"):
提示:fig, axes = plt.subplots(2, 2, figsize=(14, 10))
"""
# TODO: 你的程式碼
pass
Loading