
題目概述
這題想解的是:當我們手上有一份玩家遊戲活動記錄,要計算「首次登入後隔天也有登入的玩家比例」是多少?
資料是玩家每天登入的記錄,我們需要找出每個玩家的首次登入日期,然後判斷他們是否在隔天也有登入。最後計算這類「忠實玩家」佔全部玩家的比例,並四捨五入至小數點後兩位。這就像我們在分析遊戲留存率、用戶黏著度時,常見的「次日留存率」指標,是評估遊戲吸引力的重要數據。
Input 格式
表格名稱為 Activity
,包含以下欄位:
- player_id:玩家ID
- device_id:設備ID
- event_date:登入日期
- games_played:當天玩的遊戲數量
每個玩家可能有多筆登入記錄,但我們只關心他們首次登入後的行為。


Output 格式
輸出一個名為 fraction
的欄位,代表首次登入後隔天也有登入的玩家比例,四捨五入到小數點後兩位。

Pandas 解法 1
只關注前兩次登入
這個方法先取每個玩家的前兩次登入記錄,然後計算這兩次登入的日期差異,找出連續登入的玩家。
Step 1: 依玩家ID和日期排序
Step 2: 使用 groupby().head(2) 取得每個玩家的前兩次登入記錄
Step 3: 計算組內日期差異,找出連續登入的玩家
Step 4: 計算連續登入玩家佔總玩家的比例
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
# 排序確保日期順序正確
activity = activity.sort_values(by=['player_id', 'event_date'])
# 取每個玩家的前兩次登入記錄
first_two_logins = activity.groupby('player_id').head(2)
# 計算組內日期差異
first_two_logins['date_diff'] = first_two_logins.groupby('player_id')['event_date'].diff().dt.days
# 找出連續登入的玩家數量
consecutive_players = first_two_logins[first_two_logins['date_diff'] == 1]['player_id'].nunique()
total_players = activity['player_id'].nunique()
# 計算比例
fraction = consecutive_players / total_players
return pd.DataFrame({'fraction': [round(fraction, 2)]})

Pandas 解法 2
取得每個玩家的下一次登入日期
Step 1: 依玩家ID和日期排序,確保時間順序正確
Step 2: 使用 shift(-1) 取得每個玩家的下一次登入日期
Step 3: 計算日期差異,找出是否隔天登入
Step 4: 只保留每個玩家的第一筆記錄(首次登入)
Step 5: 計算隔天有登入的玩家比例
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
# 排序確保日期順序正確
activity = activity.sort_values(by=['player_id', 'event_date'])
# 計算每個玩家的下一次登入日期
activity['next_login_date'] = activity.groupby('player_id')['event_date'].shift(-1)
# 計算日期差異
activity['date_diff'] = (activity['next_login_date'] - activity['event_date']).dt.days
# 只保留每個玩家的首次登入記錄
activity = activity.drop_duplicates(subset=['player_id'], keep='first')
# 計算隔天有登入的玩家比例
total_players = activity['player_id'].nunique()
consecutive_players = len(activity[activity['date_diff'] == 1])
fraction = consecutive_players / total_players
return pd.DataFrame({'fraction': [round(fraction, 2)]})

Pandas 解法 3
使用 transform('min') 找出首次登入日期
Step 1: 找出每個玩家的首次登入日期
Step 2: 找出在首次登入後一天也有登入的記錄
Step 3: 計算比例
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
# 找出每個玩家的首次登入日期
activity['first_login_date'] = activity.groupby('player_id')['event_date'].transform('min')
# 找出在首次登入後一天也有登入的記錄
consecutive_logins = activity[activity['event_date'] == activity['first_login_date'] + pd.DateOffset(1)]
# 計算比例
consecutive_players = consecutive_logins['player_id'].nunique()
total_players = activity['player_id'].nunique()
fraction = consecutive_players / total_players
return pd.DataFrame({'fraction': [round(fraction, 2)]})

Pandas 解法 3.1
transform('min') + Timedelta 找出次日登入
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
# 找出每個玩家的首次登入日期
first_login_dates = activity.groupby('player_id')['event_date'].transform('min')
# 找出在首次登入後一天也有登入的玩家
consecutive_players = activity['player_id'][
activity['event_date'] == first_login_dates + pd.Timedelta(days=1)
].nunique()
# 計算比例
total_players = activity['player_id'].nunique()
fraction = consecutive_players / total_players
return pd.DataFrame({'fraction': [round(fraction, 2)]})
Pandas 解法 4
使用 merge 合併首次登入資料
Step 1: 找出每個玩家的首次登入日期
Step 2: 合併首次登入資料
Step 3: 找出在首次登入後一天也有登入的記錄
Step 4: 計算比例
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
# 找出每個玩家的首次登入日期
first_logins = activity.groupby('player_id')['event_date'].min().reset_index()
first_logins = first_logins.rename(columns={'event_date': 'first_login_date'})
# 合併首次登入資料
merged_df = activity.merge(first_logins, on='player_id')
# 找出在首次登入後一天也有登入的記錄
consecutive_logins = merged_df[merged_df['event_date'] == merged_df['first_login_date'] + pd.DateOffset(1)]
# 計算比例
consecutive_players = consecutive_logins['player_id'].nunique()
total_players = activity['player_id'].nunique()
fraction = consecutive_players / total_players
return pd.DataFrame({'fraction': [round(fraction, 2)]})

Pandas 解法 5
使用 rank() 標記登入順序
Step 1: 為每個玩家的登入記錄標記順序
Step 2: 只保留前兩次登入記錄
Step 3: 計算每個玩家的首次和次次登入日期
Step 4: 計算日期差異
Step 5: 找出連續登入的玩家數量
Step 6: 計算比例
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
# 為每個玩家的登入記錄標記順序
activity['login_rank'] = activity.groupby('player_id')['event_date'].rank(
method='first', ascending=True
)
# 只保留前兩次登入記錄
total_players = activity['player_id'].nunique()
filtered_activity = activity[activity['login_rank'] <= 2]
# 計算每個玩家的首次和次次登入日期
player_stats = filtered_activity.groupby('player_id').agg(
last_login=('event_date', 'max'),
first_login=('event_date', 'min')
).reset_index()
# 計算日期差異
player_stats['date_diff'] = (player_stats['last_login'] - player_stats['first_login']).dt.days
# 找出連續登入的玩家數量
consecutive_players = len(player_stats[player_stats['date_diff'] == 1])
# 計算比例
fraction = consecutive_players / total_players
return pd.DataFrame({'fraction': [round(fraction, 2)]})

謝謝您花時間將此篇文章讀完,若覺得對您有幫助可以幫忙按個讚、分享來或是珍藏喔!也歡迎Follow我的Threads/ FB,持續追蹤生產力工具、商業分析、商業英文的實用範例,提升自己的職場力喔!