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
24 changes: 24 additions & 0 deletions homework/m1_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@
def green_mean():
"""建立 [10, 20, 30, 40, 50],回傳所有元素的平均值 (float)"""
# TODO: 你的程式碼
arr = np.array([10, 20, 30, 40, 50])
return float(np.mean(arr))
pass


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


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


Expand All @@ -42,6 +48,8 @@ def green_filter():
def yellow_expensive_count(prices):
"""回傳單價 > 1000 的商品數量 (int)"""
# TODO: 你的程式碼
count = np.sum(prices > 1000)
return int(count)
pass


Expand All @@ -51,6 +59,8 @@ def yellow_top3_stock_indices(stocks):
提示:np.argsort
"""
# TODO: 你的程式碼
index = np.argsort(stocks)[::-1]
return index[:3]
pass


Expand All @@ -60,6 +70,10 @@ def yellow_restock_cost(prices, stocks):
提示:布林遮罩 + .sum()
"""
# TODO: 你的程式碼
mask = prices < 500
number = np.sum(mask)
totol_cost = np.sum(prices[mask] * 50)
return totol_cost
pass


Expand All @@ -77,4 +91,14 @@ def red_double11_prices(prices, stocks):
提示:np.where 可以巢狀使用
"""
# TODO: 你的程式碼
finall_price = np.where(
stocks >= 100,
prices * 0.7,
np.where(
stocks >= 20,
prices * 0.9,
prices
)
)
return finall_price
pass
18 changes: 18 additions & 0 deletions homework/m2_pandas_cleaning.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def green_read_csv():
提示:pd.read_csv()
"""
# TODO: 你的程式碼
df = pd.read_csv("../datasets/ecommerce/orders_raw.csv")
return df
pass


Expand All @@ -29,6 +31,7 @@ def green_shape(df):
提示:df.shape
"""
# TODO: 你的程式碼
return df.shape
pass


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


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


Expand All @@ -63,6 +70,9 @@ def yellow_clean_amount(df):
提示:.str.replace() + .astype(float)
"""
# TODO: 你的程式碼
new_df = df.copy()
new_df['amount'] = new_df['amount'].str.replace('$', '', regex=False).str.replace(',', '',regex=False).astype(float)
return new_df
pass


Expand All @@ -72,6 +82,7 @@ def yellow_drop_duplicates(df):
提示:df.drop_duplicates()
"""
# TODO: 你的程式碼
return df.drop_duplicates()
pass


Expand All @@ -93,4 +104,11 @@ def red_clean_orders(path):
提示:pd.to_datetime(errors='coerce')
"""
# TODO: 你的程式碼
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'], how='any')
df = df.drop_duplicates()
return df
pass
24 changes: 24 additions & 0 deletions homework/m3_pandas_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,26 @@ def green_load_and_merge():
提示:pd.merge(how='left')
"""
# TODO: 你的程式碼
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')
merged_df = pd.merge(orders, customers, on='customer_id', how='left')
final_df = pd.merge(merged_df, products, on='product_id', how='left')
return final_df
pass


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


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


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


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


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


Expand All @@ -94,4 +111,11 @@ def red_rfm_top5(df):
提示:groupby('customer_id').agg(...)
"""
# TODO: 你的程式碼
rfm = df.groupby(['customer_id', 'customer_name']).agg(
R=('order_date', 'max'),
F=('order_date', 'count'),
M=('amount', 'sum')
).reset_index()
rfm_sorted = rfm.sort_values(by='M', ascending=False)
return rfm_sorted.head(5)
pass
29 changes: 28 additions & 1 deletion homework/m4_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

def _load_data():
"""輔助函式:讀取並解析日期"""
df = pd.read_csv("datasets/ecommerce/orders_enriched.csv",
df = pd.read_csv("../datasets/ecommerce/orders_enriched.csv",
parse_dates=["order_date"])
return df

Expand All @@ -27,6 +27,9 @@ def green_avg_by_month():
提示:df['order_date'].dt.month
"""
# TODO: 你的程式碼
df = _load_data()
monthly_avg = df.groupby(df['order_date'].dt.month)['amount'].mean()
return monthly_avg
pass


Expand All @@ -37,6 +40,9 @@ def green_top3_dates():
提示:value_counts().head(3)
"""
# TODO: 你的程式碼
df = _load_data()
date_counts = df['order_date'].value_counts()
return date_counts.head(3)
pass


Expand All @@ -46,6 +52,10 @@ def green_date_range():
格式為 pandas Timestamp
"""
# TODO: 你的程式碼
df = _load_data()
min_date = df['order_date'].min()
max_date = df['order_date'].max()
return (min_date, max_date)
pass


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


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


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


Expand All @@ -101,4 +118,14 @@ def red_monthly_report():
提示:resample + agg + pct_change
"""
# TODO: 你的程式碼
df = _load_data()
df = df.set_index('order_date')
report = df.resample('ME').agg(
order_count=('amount', 'count'),
revenue=('amount', 'sum'),
active_customers=('customer_id', 'nunique')
)
report['avg_order_value'] = report['revenue'] / report['order_count']
report['revenue_growth'] = report['revenue'].pct_change()
return report
pass
60 changes: 59 additions & 1 deletion homework/m5_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

def _load_data():
"""輔助函式:讀取資料"""
return pd.read_csv("datasets/ecommerce/orders_enriched.csv",
return pd.read_csv("../datasets/ecommerce/orders_enriched.csv",
parse_dates=["order_date"])


Expand All @@ -29,6 +29,11 @@ def green_bar_category():
提示:sns.countplot 或 value_counts().plot.bar()
"""
# TODO: 你的程式碼
df = _load_data()
fig, ax = plt.subplots(figsize=(10, 6))
sns.countplot(data=df, x='category', ax=ax)
ax.set_title("Order Count by Category")
return fig
pass


Expand All @@ -39,6 +44,11 @@ def green_hist_amount():
提示:sns.histplot(bins=20) 或 plt.hist()
"""
# TODO: 你的程式碼
df = _load_data()
fig, ax = plt.subplots(figsize=(10, 6))
sns.histplot(data=df, x='amount', bins=20, ax=ax)
ax.set_title("Distribution of Order Amounts")
return fig
pass


Expand All @@ -51,6 +61,13 @@ def green_set_labels():
回傳 matplotlib Figure 物件
"""
# TODO: 你的程式碼
data = {'A': 100, 'B': 200, 'C': 300}
fig, ax = plt.subplots()
ax.bar(data.keys(), data.values())
ax.set_title("Simple Bar Chart")
ax.set_xlabel("Category")
ax.set_ylabel("Values")
return fig
pass


Expand All @@ -68,6 +85,15 @@ def yellow_line_region_trend():
提示:分別 groupby 再 plot,或用 sns.lineplot(hue='region')
"""
# TODO: 你的程式碼
df = _load_data()
target_regions = df[df['region'].isin(['North', 'South'])]
trend_data = target_regions.groupby([target_regions['order_date'].dt.month, 'region'])['amount'].sum().unstack()
fig, ax = plt.subplots(figsize=(10, 6))
sns.lineplot(data=target_regions, x=target_regions['order_date'].dt.month, y='amount', hue='region', estimator='sum', ax=ax)
ax.set_title("Monthly Revenue Trend: North vs South")
ax.set_xlabel("Month")
ax.set_ylabel("Total Revenue")
return fig
pass


Expand All @@ -78,6 +104,11 @@ def yellow_box_vip():
提示:sns.boxplot(x='vip_level', y='amount', data=df)
"""
# TODO: 你的程式碼
df = _load_data()
fig, ax = plt.subplots(figsize=(10, 6))
sns.boxplot(data=df, x='vip_level', y='amount', ax=ax)
ax.set_title("Order Amount Distribution by VIP Level")
return fig
pass


Expand All @@ -88,6 +119,11 @@ def yellow_scatter_price_amount():
提示:plt.scatter() 或 sns.scatterplot()
"""
# TODO: 你的程式碼
df = _load_data()
fig, ax = plt.subplots(figsize=(10, 6))
sns.scatterplot(data=df, x='unit_price', y='amount', ax=ax)
ax.set_title("Unit Price vs Order Amount")
return fig
pass


Expand All @@ -107,4 +143,26 @@ def red_category_dashboard(category="Electronics"):
提示:fig, axes = plt.subplots(2, 2, figsize=(14, 10))
"""
# TODO: 你的程式碼
df = _load_data()
cat_df = df[df['category'] == category].copy()
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle(f"Dashboard: {category}", fontsize=20)
monthly_rev = cat_df.set_index('order_date').resample('ME')['amount'].sum()
axes[0, 0].plot(monthly_rev.index, monthly_rev.values, marker='o', color='b')
axes[0, 0].set_title("Monthly Revenue Trend")
axes[0, 0].tick_params(axis='x', rotation=45)

region_rev = cat_df.groupby('region')['amount'].sum().sort_values(ascending=False)
sns.barplot(x=region_rev.index, y=region_rev.values, ax=axes[0, 1])
axes[0, 1].set_title("Revenue by Region")

top5_prod = cat_df.groupby('product_name')['amount'].sum().nlargest(5)
sns.barplot(x=top5_prod.values, y=top5_prod.index, ax=axes[1, 0], orient='h')
axes[1, 0].set_title("Top 5 Products by Revenue")

sns.histplot(cat_df['amount'], bins=15, kde=True, ax=axes[1, 1])
axes[1, 1].set_title("Order Amount Distribution")

plt.tight_layout(rect=[0, 0.03, 1, 0.95])
return fig
pass
Loading
Loading