Leetcode 解鎖 - Game Play Analysis IV via Pandas (550)

更新於 發佈於 閱讀時間約 14 分鐘
raw-image
題目概述

問題連結

這題想解的是:當我們手上有一份玩家遊戲活動記錄,要計算「首次登入後隔天也有登入的玩家比例」是多少?

資料是玩家每天登入的記錄,我們需要找出每個玩家的首次登入日期,然後判斷他們是否在隔天也有登入。最後計算這類「忠實玩家」佔全部玩家的比例,並四捨五入至小數點後兩位。

這就像我們在分析遊戲留存率、用戶黏著度時,常見的「次日留存率」指標,是評估遊戲吸引力的重要數據。

Input 格式

表格名稱為 Activity,包含以下欄位:

  • player_id:玩家ID
  • device_id:設備ID
  • event_date:登入日期
  • games_played:當天玩的遊戲數量

每個玩家可能有多筆登入記錄,但我們只關心他們首次登入後的行為。

raw-image
raw-image
Output 格式

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

raw-image


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)]})
raw-image


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)]})
raw-image


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)]})
raw-image


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)]})
raw-image


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)]})
raw-image




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




留言
avatar-img
留言分享你的想法!
avatar-img
DigNo Ape 數遊原人
50會員
133內容數
我們秉持著從原人進化的精神,不斷追求智慧的累積和工具的運用來提升生產力。我們相信,每一個成員都擁有無限的潛力,透過學習和實踐,不斷成長和進步。
你可能也想看
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
當你邊吃粽子邊看龍舟競賽直播的時候,可能會順道悼念一下2300多年前投江的屈原。但你知道端午節及其活動原先都與屈原毫無關係嗎?這是怎麼回事呢? 本文深入探討端午節設立初衷、粽子、龍舟競渡與屈原自沉四者。看完這篇文章,你就會對端午、粽子、龍舟和屈原的四角關係有新的認識喔。那就讓我們一起解開謎團吧!
Thumbnail
當你邊吃粽子邊看龍舟競賽直播的時候,可能會順道悼念一下2300多年前投江的屈原。但你知道端午節及其活動原先都與屈原毫無關係嗎?這是怎麼回事呢? 本文深入探討端午節設立初衷、粽子、龍舟競渡與屈原自沉四者。看完這篇文章,你就會對端午、粽子、龍舟和屈原的四角關係有新的認識喔。那就讓我們一起解開謎團吧!
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
題目敘述 Count Number of Teams 給定一個輸入陣列rating,裡面代表每位成員的評分 挑選三位成員,對應到三個index i, j, k 且 i < j < k 如果rating[i] < rating[j] < rating[k] ,則此三人可以組成一隊。 或者ra
Thumbnail
題目敘述 Count Number of Teams 給定一個輸入陣列rating,裡面代表每位成員的評分 挑選三位成員,對應到三個index i, j, k 且 i < j < k 如果rating[i] < rating[j] < rating[k] ,則此三人可以組成一隊。 或者ra
Thumbnail
LeetCode 是一個程式語言版的線上題庫平臺,提供題目描述、程式碼區塊、解題者分享的解法和疑問討論。藉由這篇文章分享我在 LeetCode 上的使用經驗和觀點,包括刷題的重要性、解題心態和練習目標。
Thumbnail
LeetCode 是一個程式語言版的線上題庫平臺,提供題目描述、程式碼區塊、解題者分享的解法和疑問討論。藉由這篇文章分享我在 LeetCode 上的使用經驗和觀點,包括刷題的重要性、解題心態和練習目標。
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
題目敘述 題目會給我們一個定義好的類別和function介面,要求我們實作建構子和ping() function來滿足指定的需求。 RecentCounter類別的建構子 建構子應該初始化來電紀錄,內容為空(零筆資料) int ping(int t) t代表來電時刻,單位是毫秒m
Thumbnail
題目敘述 題目會給我們一個定義好的類別和function介面,要求我們實作建構子和ping() function來滿足指定的需求。 RecentCounter類別的建構子 建構子應該初始化來電紀錄,內容為空(零筆資料) int ping(int t) t代表來電時刻,單位是毫秒m
Thumbnail
題目會給定一個輸入陣列temperatures ,分別代表每一天的溫度。 請計算每一天還要再過幾天才會遇到更溫暖的日子,如果遇不到,則回填0。 請以陣列的形式返回答案。 題目的原文敘述 約束條件 Constraints: 1 <= temperatures.length <= 10^
Thumbnail
題目會給定一個輸入陣列temperatures ,分別代表每一天的溫度。 請計算每一天還要再過幾天才會遇到更溫暖的日子,如果遇不到,則回填0。 請以陣列的形式返回答案。 題目的原文敘述 約束條件 Constraints: 1 <= temperatures.length <= 10^
Thumbnail
題目敘述 題目會給定一個整數陣列arr,要求我們判斷是否每個元素的出現次數都不同? 題目的原文敘述 測試範例 Example 1: Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurre
Thumbnail
題目敘述 題目會給定一個整數陣列arr,要求我們判斷是否每個元素的出現次數都不同? 題目的原文敘述 測試範例 Example 1: Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurre
Thumbnail
題目敘述 題目會給定我們一個比賽紀錄陣列matches,裡面以pair的方式儲存,每個pair的第一個欄位代表這場比賽的贏家ID,第二個欄位代表這場比賽的輸家ID。 題目要求我們找出所有沒有輸的玩家ID,和只輸一場的玩家ID。 計算時,只考慮有比賽紀錄的玩家。 輸出時,依照遊戲玩家的ID,從
Thumbnail
題目敘述 題目會給定我們一個比賽紀錄陣列matches,裡面以pair的方式儲存,每個pair的第一個欄位代表這場比賽的贏家ID,第二個欄位代表這場比賽的輸家ID。 題目要求我們找出所有沒有輸的玩家ID,和只輸一場的玩家ID。 計算時,只考慮有比賽紀錄的玩家。 輸出時,依照遊戲玩家的ID,從
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News