[코딩테스트]/[Pandas]

[LeetCode - Pandas] (Easy) 1141. User Activity for the Past 30 Days I

잰잰' 2025. 4. 22. 13:55
Table: Activity

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| user_id       | int     |
| session_id    | int     |
| activity_date | date    |
| activity_type | enum    |
+---------------+---------+

 

이 테이블에는 중복된 행이 있을 수 있습니다.
activity_type 열은 ('open_session', 'end_session', 'scroll_down', 'send_message') 유형의 ENUM(카테고리)입니다.
이 테이블은 소셜 미디어 웹사이트의 사용자 활동을 보여줍니다.
각 세션은 정확히 하나의 사용자에 속한다는 점에 유의하세요.

 

문제

2019-07-27을 포함하여 30일 동안의 일일 활성 사용자 수를 찾는 솔루션을 작성하세요. 사용자는 해당 날짜에 최소한 하나의 활동을 했다면 그 날에 활동한 것으로 간주합니다.

결과 테이블은 임의의 순서로 반환하세요.

결과 형식은 다음 예시와 같습니다.

Example 1:

Input: 
Activity table:
+---------+------------+---------------+---------------+
| user_id | session_id | activity_date | activity_type |
+---------+------------+---------------+---------------+
| 1       | 1          | 2019-07-20    | open_session  |
| 1       | 1          | 2019-07-20    | scroll_down   |
| 1       | 1          | 2019-07-20    | end_session   |
| 2       | 4          | 2019-07-20    | open_session  |
| 2       | 4          | 2019-07-21    | send_message  |
| 2       | 4          | 2019-07-21    | end_session   |
| 3       | 2          | 2019-07-21    | open_session  |
| 3       | 2          | 2019-07-21    | send_message  |
| 3       | 2          | 2019-07-21    | end_session   |
| 4       | 3          | 2019-06-25    | open_session  |
| 4       | 3          | 2019-06-25    | end_session   |
+---------+------------+---------------+---------------+
Output: 
+------------+--------------+ 
| day        | active_users |
+------------+--------------+ 
| 2019-07-20 | 2            |
| 2019-07-21 | 2            |
+------------+--------------+

설명 : 활성 사용자가 없는 날짜는 신경 쓰지 않음을 유의하세요.

 

✏️ 풀이

import pandas as pd

def user_activity(activity: pd.DataFrame) -> pd.DataFrame:
    # 시작 날짜 구하기
    end_date = pd.to_datetime('2019-07-27')
    start_date = end_date - pd.DateOffset(days=30)
    
    # 범위에 해당하는 데이터 필터
    df = activity[activity['activity_date'].between(start_date, end_date)]

    # 사용자 수 카운트 (중복제거)
    result = df.rename(columns={"activity_date" : "day"}).groupby('day')['user_id'].nunique().reset_index(name='active_users')

    return result

 

📚 개념정리

1. between() ? 특정 범위 내에 있는 값을 선택할 때 사용하는 함수

Series.between(left, right, inclusive='both')

- left : 범위의 왼쪽 경계값

- right : 범위의 오른쪽 경계값

- inclusive : 범위에 포함될 경계값을 설정 

   - both : 양쪽 끝 값 포함(기본값)

   - left : 왼쪽 끝 값만 포함

   - right : 오른쪽 끝 값만 포함

   - neither : 양쪽 끝 값 모두 제외

 

2. to_datetime() ? 문자열, 숫자 등의 데이터를 datetime 객체로 변환하는 함수

pandas.to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False)

 

- arg : 날짜로 변환할 값 (문자열, 리스트, 시리즈 등)

- errors : 오류 발생 시 처리 방법. 'raise' (기본값)은 오류를 발생시키고, 'coerce'는 오류 발생 시 NaT(Not a Time)로 처리, 'ignore'는 그대로 반환

- dayfirst : True일 경우, 날짜 형식에서 첫 번째 값을 일(day)로 간주

- yearfirst : True일 경우, 날짜 형식에서 첫 번째 값을 연도(year)로 간주

 

3. DateOffset() ? 날짜에 특정 날짜 단위를 더하거나 빼는 데 사용되는 객체

pandas.DateOffset(years=0, months=0, days=0, hours=0, minutes=0, seconds=0)

 

 

- years : 연도 단위로 더할 수 있는 값

- months : 월 단위로 더할 수 있는 값

- days : 일 단위로 더할 수 있는 값

- hours, minutes, seconds : 시간, 분, 초 단위로 더할 수 있는 값