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


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



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

#pass
arr = np.array([10,20,30,40,50])
return arr[arr>25]



# ============================================================
# 🟡 核心題(每題 15 分,共 45 分)
Expand All @@ -42,7 +48,8 @@ def green_filter():
def yellow_expensive_count(prices):
"""回傳單價 > 1000 的商品數量 (int)"""
# TODO: 你的程式碼
pass
#pass
return (prices > 1000).sum()


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


def yellow_restock_cost(prices, stocks):
Expand All @@ -60,7 +68,8 @@ def yellow_restock_cost(prices, stocks):
提示:布林遮罩 + .sum()
"""
# TODO: 你的程式碼
pass
#pass
return (prices[ prices < 500] * 50).sum()


# ============================================================
Expand All @@ -77,4 +86,13 @@ def red_double11_prices(prices, stocks):
提示:np.where 可以巢狀使用
"""
# TODO: 你的程式碼
pass
#pass
new_prices = np.where(stocks>=100, prices*0.7, np.where( stocks>=20, prices*0.9, prices))
return new_prices


if __name__ == '__main__':
print(green_mean())
print(green_double())
print(green_filter())
print(red_double11_prices(200,100))
45 changes: 34 additions & 11 deletions homework/m2_pandas_cleaning.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ def green_read_csv():
提示:pd.read_csv()
"""
# TODO: 你的程式碼
pass
#pass
df= pd.read_csv("datasets/ecommerce/orders_raw.csv")
return df


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


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



# ============================================================
# 🟡 核心題(每題 15 分,共 45 分)
# ============================================================

def yellow_clean_columns(df):
def yellow_clean_columns(df:pd.DataFrame ):
"""
清理欄位名稱:去除前後空白、全部轉小寫
回傳清理後的 DataFrame(不要修改原始 df)
提示:df.columns.str.strip().str.lower()
"""
# TODO: 你的程式碼
pass
#pass
df_new = df.copy()
df_new.columns = df.columns.str.strip().str.lower()
return df_new


def yellow_clean_amount(df):
def yellow_clean_amount(df:pd.DataFrame ):
"""
清理 amount 欄位:移除 '$' 和 ',' 符號,轉為 float
假設欄位名稱已經是小寫的 'amount'
回傳清理後的 DataFrame(不要修改原始 df)
提示:.str.replace() + .astype(float)
"""
# TODO: 你的程式碼
pass
df_new = df.copy()
df_new['amount'] = df['amount'].str.strip('$').str.replace(',','').astype(float)
#pass
return df_new


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


# ============================================================
Expand All @@ -93,4 +105,15 @@ def red_clean_orders(path):
提示:pd.to_datetime(errors='coerce')
"""
# TODO: 你的程式碼
pass
#pass
df= pd.read_csv("datasets/ecommerce/orders_raw.csv")
df.columns = df.columns.str.strip().str.lower()
df['amount'] = df['amount'].str.strip('$').str.replace(',','').astype(float)
df['order_date'] = pd.to_datetime(df['order_date'], errors='coerce')
df = df.dropna(subset=['order_date', 'amount'])
#這個不確定, 先comment
df['qty'] = df['qty'].fillna(df['qty'].median)

df = df.drop_duplicates()
return df

53 changes: 38 additions & 15 deletions homework/m3_pandas_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,60 +24,78 @@ def green_load_and_merge():
提示:pd.merge(how='left')
"""
# TODO: 你的程式碼
pass


def green_row_count(df):
#pass
order = pd.read_csv("datasets/ecommerce/orders_clean.csv")
customer = pd.read_csv("datasets/ecommerce/customers.csv")
prod = pd.read_csv("datasets/ecommerce/products.csv")
df = (
order.merge(customer, how='left', on='customer_id')
.merge(prod, how='left', on='product_id')
)
return df



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


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


# ============================================================
# 🟡 核心題(每題 15 分,共 45 分)
# ============================================================

def yellow_top_category(df):
def yellow_top_category(df:pd.DataFrame):
"""
哪個商品類別 (category) 的總營收最高?
回傳該類別名稱 (str)
提示:groupby('category')['amount'].sum()
"""
# TODO: 你的程式碼
pass
#pass
return df.groupby('category')['amount'].sum().idxmax()


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



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


# ============================================================
# 🔴 挑戰題(25 分)
# ============================================================

def red_rfm_top5(df):
def red_rfm_top5(df:pd.DataFrame):
"""
RFM 分析:找出最有價值的前 5 位客戶

Expand All @@ -94,4 +112,9 @@ def red_rfm_top5(df):
提示:groupby('customer_id').agg(...)
"""
# TODO: 你的程式碼
pass
#pass
rfm_h5 = df.groupby('customer_id').agg(R=('order_date','max'),
F=('order_id','count'),
M=('amount','sum')).reset_index().sort_values('M', ascending=False).head(5)
rfm_ans = rfm_h5.merge(df[['customer_name','customer_id']], how='left', on='customer_id').drop_duplicates()
return rfm_ans
55 changes: 45 additions & 10 deletions homework/m4_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
"""
import pandas as pd

gdf:pd.DataFrame

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


_load_data()
# ============================================================
# 🟢 送分題(每題 10 分,共 30 分)
# ============================================================
Expand All @@ -27,7 +30,12 @@ def green_avg_by_month():
提示:df['order_date'].dt.month
"""
# TODO: 你的程式碼
pass
#pass
global gdf
gdf['月份'] = gdf['order_date'].dt.month
month_avg = gdf.groupby('月份')['amount'].mean()
month_avg.name = '平均金額'
return month_avg


def green_top3_dates():
Expand All @@ -37,7 +45,12 @@ def green_top3_dates():
提示:value_counts().head(3)
"""
# TODO: 你的程式碼
pass
#pass
global gdf
date_ord = gdf['order_date'].value_counts()
date_ord = date_ord.rename_axis('日期')
date_ord.name='訂單數'
return date_ord.head(3)


def green_date_range():
Expand All @@ -46,7 +59,11 @@ def green_date_range():
格式為 pandas Timestamp
"""
# TODO: 你的程式碼
pass
#pass
global gdf
dmax = gdf['order_date'].max()
dmin = gdf['order_date'].min()
return dmin, dmax


# ============================================================
Expand All @@ -60,28 +77,35 @@ def yellow_monthly_revenue():
提示:set_index('order_date').resample('ME')['amount'].sum()
"""
# TODO: 你的程式碼
pass
#pass
global gdf
ts = gdf.set_index('order_date').sort_index()
return ts['amount'].resample('ME').sum()


def yellow_rolling_avg(monthly_revenue):
def yellow_rolling_avg(monthly_revenue:pd.Series):
"""
計算 3 個月移動平均
接收 yellow_monthly_revenue() 的結果作為輸入
回傳 Series(同樣 index,values=移動平均,前 2 筆可為 NaN)
提示:.rolling(window=3).mean()
"""
# TODO: 你的程式碼
pass
#pass
return monthly_revenue.rolling(window=3).mean()


def yellow_category_median(df):
def yellow_category_median(df:pd.DataFrame):
"""
計算每個商品類別 (category) 的訂單金額中位數,由高到低排序
回傳 Series(index=category, values=中位數)
提示:groupby + median + sort_values
"""
# TODO: 你的程式碼
pass
#pass
cat_med = df.groupby('category')['amount'].median().sort_values(ascending=False)
cat_med.name = '中位數'
return cat_med


# ============================================================
Expand All @@ -101,4 +125,15 @@ def red_monthly_report():
提示:resample + agg + pct_change
"""
# TODO: 你的程式碼
pass
#pass
global gdf
ts = gdf.set_index('order_date').sort_index()
mon_report = ts.resample('ME').agg(
order_count=('order_id','count'),
active_customers=('customer_id','nunique'),
revenue=('amount','sum'),
avg_order_value=('amount','mean')
)
mon_report['revenue_growth'] = mon_report['revenue'].pct_change()
return mon_report

Loading
Loading