시계열 데이터
import pandas as pd
netflix_titles = pd.read_csv('https://raw.githubusercontent.com/minaahayley/Python/main/data/netflix_titles.csv')
netflix_titles.sample()
| show_id | type | title | director | cast | country | date_added | release_year | rating | duration | listed_in | description | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 6183 | s6184 | Movie | Are We Done Yet? | Khaled El Halafawy | Ahmed Eid, Ayten Amer, Ahmed Fouad Selim, Mohs... | Egypt | August 1, 2019 | 2018 | TV-14 | 87 min | Comedies, Dramas, International Movies | When authorities arrest his young son, a taxi ... |
pd.to_datetime()¶
- 날짜, 시간 정보를 담은 column은 기본적으로 object 형태로 자료형이 지정되어, datetime 자료형으로 변환하여야 한다.
- pd.to_datetime() 함수를 사용하여 시간 형식의 object 자료형 column을 datetime 형식으로 손쉽게 바꿀 수 있다.
netflix_titles['date_added'].dtype
dtype('O')
netflix_titles['date'] = pd.to_datetime(netflix_titles['date_added'])
netflix_titles['date']
0 2021-09-25
1 2021-09-24
2 2021-09-24
3 2021-09-24
4 2021-09-24
...
8802 2019-11-20
8803 2019-07-01
8804 2019-11-01
8805 2020-01-11
8806 2019-03-02
Name: date, Length: 8807, dtype: datetime64[ns]
dt.strftime()¶
- dt.strftime() 함수 안에 format을 지정하여 datetime 객체를 문자열(string)로 변환 할 수 있다.
netflix_titles['ym'] = pd.to_datetime(netflix_titles['date_added']).dt.strftime('%Y-%m')
netflix_titles['ym']
0 2021-09
1 2021-09
2 2021-09
3 2021-09
4 2021-09
...
8802 2019-11
8803 2019-07
8804 2019-11
8805 2020-01
8806 2019-03
Name: ym, Length: 8807, dtype: object
dt.strftime() 함수를 이용하여 문자열(string)로 변환된 자료형은 pd.to_datetime() 함수를 이용하여, datetime 자료형으로 다시 변환 할 수 있다.
이 경우, 해당 월의 첫번째 일자로 데이터가 추출된다.
netflix_titles['ym_dt'] = pd.to_datetime(netflix_titles['ym'], format='%Y-%m')
netflix_titles['ym_dt']
0 2021-09-01
1 2021-09-01
2 2021-09-01
3 2021-09-01
4 2021-09-01
...
8802 2019-11-01
8803 2019-07-01
8804 2019-11-01
8805 2020-01-01
8806 2019-03-01
Name: ym_dt, Length: 8807, dtype: datetime64[ns]
dt.to_period()¶
- Period 자료형은 datetime 자료형을 다시 기간에 따른 자료형으로 이용하고자 할 때 사용한다.
- Period 객체는 datetime 타입에 대해서만 적용 가능하며, to_period(freq='기간인수')를 통해 기간 주기를 생성한다.
월 단위의 기간 주기 만들기 (monthly period frequencies)
netflix_titles['date'].dt.to_period('M')
0 2021-09
1 2021-09
2 2021-09
3 2021-09
4 2021-09
...
8802 2019-11
8803 2019-07
8804 2019-11
8805 2020-01
8806 2019-03
Name: date, Length: 8807, dtype: period[M]
분기 단위의 기간 주기 만들기 (quarterly period frequencies)
netflix_titles['date'].dt.to_period('Q')
0 2021Q3
1 2021Q3
2 2021Q3
3 2021Q3
4 2021Q3
...
8802 2019Q4
8803 2019Q3
8804 2019Q4
8805 2020Q1
8806 2019Q1
Name: date, Length: 8807, dtype: period[Q-DEC]
period 객체는 int로 변환이 가능하며, month-diff 등을 계산하기 위한 기간 수로 출력이 가능하다.
netflix_titles['date'].dt.to_period('M').astype(int)
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:1: FutureWarning: casting period[M] values to int64 with .astype(...) is deprecated and will raise in a future version. Use .view(...) instead. """Entry point for launching an IPython kernel.
0 620
1 620
2 620
3 620
4 620
...
8802 598
8803 594
8804 598
8805 600
8806 590
Name: date, Length: 8807, dtype: int64
netflix_titles['date'].dt.to_period('Q').astype(int)
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:1: FutureWarning: casting period[Q-DEC] values to int64 with .astype(...) is deprecated and will raise in a future version. Use .view(...) instead. """Entry point for launching an IPython kernel.
0 206
1 206
2 206
3 206
4 206
...
8802 199
8803 198
8804 199
8805 200
8806 196
Name: date, Length: 8807, dtype: int64
datetime 객체는 기간에 따른 자료형이 아니기 때문에 int로 변환하는 경우 period 객체와 결과가 다르다.
dt.strftime() 함수를 이용하여 변환된 문자열 자료형은 int로 변환 할 수 없다.
pd.to_datetime(netflix_titles['ym'], format='%Y-%m').astype(int)
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:1: FutureWarning: casting datetime64[ns] values to int64 with .astype(...) is deprecated and will raise in a future version. Use .view(...) instead. """Entry point for launching an IPython kernel.
0 1630454400000000000
1 1630454400000000000
2 1630454400000000000
3 1630454400000000000
4 1630454400000000000
...
8802 1572566400000000000
8803 1561939200000000000
8804 1572566400000000000
8805 1577836800000000000
8806 1551398400000000000
Name: ym, Length: 8807, dtype: int64
dt.to_period('Q') 함수를 이용하여 만든 분기 기간 주기는 그래프로 그리는 경우 분기 순으로 정렬이 되지 않는다.
분기 기간 주기를 dt.strftime() 함수를 사용하여 포맷팅을 지정하여 그래프를 그리는 경우 분기 순으로 정렬 할 수 있다.
netflix_titles['date'].dt.to_period('Q').dt.strftime('%Y-%q')
0 2021-3
1 2021-3
2 2021-3
3 2021-3
4 2021-3
...
8802 2019-4
8803 2019-3
8804 2019-4
8805 2020-1
8806 2019-1
Name: date, Length: 8807, dtype: object
pd.Categorical()¶
- pd.Categorical() 함수를 이용하여 요일 정보 정렬하기
- datetime 자료형은 dt accessor를 이용하여 요일 정보를 추출 할 수 있다.
netflix_titles['date']
0 2021-09-25
1 2021-09-24
2 2021-09-24
3 2021-09-24
4 2021-09-24
...
8802 2019-11-20
8803 2019-07-01
8804 2019-11-01
8805 2020-01-11
8806 2019-03-02
Name: date, Length: 8807, dtype: datetime64[ns]
netflix_titles['dayname'] = netflix_titles['date'].dt.day_name()
netflix_titles['dayname']
0 Saturday
1 Friday
2 Friday
3 Friday
4 Friday
...
8802 Wednesday
8803 Monday
8804 Friday
8805 Saturday
8806 Saturday
Name: dayname, Length: 8807, dtype: object
pd.Categorical() 함수를 이용하여 리스트로 지정한 순으로 요일 정보를 정렬 할 수 있다.
dayname = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
pd.Categorical(netflix_titles['dayname'], categories=dayname, ordered=True)
['Saturday', 'Friday', 'Friday', 'Friday', 'Friday', ..., 'Wednesday', 'Monday', 'Friday', 'Saturday', 'Saturday']
Length: 8807
Categories (7, object): ['Monday' < 'Tuesday' < 'Wednesday' < 'Thursday' < 'Friday' < 'Saturday' <
'Sunday']
relativedelta()¶
- relativedelta() 함수를 이용하여 YOY 구하기
from dateutil.relativedelta import relativedelta
netflix_titles['date']
0 2021-09-25
1 2021-09-24
2 2021-09-24
3 2021-09-24
4 2021-09-24
...
8802 2019-11-20
8803 2019-07-01
8804 2019-11-01
8805 2020-01-11
8806 2019-03-02
Name: date, Length: 8807, dtype: datetime64[ns]
datetime 자료형 column에 relativedelta() 함수를 적용하기 위해서는 apply 함수를 이용하여 element-wise 계산을 하면 된다.
date column에 NaN 값이 있는 경우 IllegalMonthError가 발생한다. date column이 NaN인 행을 모두 제거해주자.
netflix_titles = netflix_titles[netflix_titles['date'].notna()]
netflix_titles['previous_date'] = netflix_titles['date'].apply(lambda x : x - relativedelta(years=1))
1년 전 date가 제대로 출력 된 것을 확인 할 수 있다.
netflix_titles[['date','previous_date']]
| date | previous_date | |
|---|---|---|
| 0 | 2021-09-25 | 2020-09-25 |
| 1 | 2021-09-24 | 2020-09-24 |
| 2 | 2021-09-24 | 2020-09-24 |
| 3 | 2021-09-24 | 2020-09-24 |
| 4 | 2021-09-24 | 2020-09-24 |
| ... | ... | ... |
| 8802 | 2019-11-20 | 2018-11-20 |
| 8803 | 2019-07-01 | 2018-07-01 |
| 8804 | 2019-11-01 | 2018-11-01 |
| 8805 | 2020-01-11 | 2019-01-11 |
| 8806 | 2019-03-02 | 2018-03-02 |
8797 rows × 2 columns
YOY를 계산하기 위하여 groupby() 함수를 이용하여 넷플릭스 콘텐츠 수를 집계하자.
growth = netflix_titles.groupby(['date'])['title'].nunique().reset_index()
growth.sample()
| date | title | |
|---|---|---|
| 762 | 2018-10-28 | 1 |
relativedelta() 함수를 이용하여, date를 다시 계산하자.
growth['previous_date'] = growth['date'].apply(lambda x : x - relativedelta(years=1))
growth.sample()
| date | title | previous_date | |
|---|---|---|---|
| 306 | 2017-03-18 | 2 | 2016-03-18 |
YOY를 계산하기 위하여 셀프 조인하자.
growth = growth.merge(growth, how='left', left_on='previous_date', right_on='date')
growth.sample()
| date_x | title_x | previous_date_x | date_y | title_y | previous_date_y | |
|---|---|---|---|---|---|---|
| 909 | 2019-04-10 | 4 | 2018-04-10 | 2018-04-10 | 1.0 | 2017-04-10 |
growth = growth[['date_x', 'title_x', 'previous_date_x', 'title_y']].rename({'date_x': 'date', 'title_x':'contents', 'previous_date_x':'previous_date', 'title_y':'previous_contents'}, axis = 1)
growth.sample()
| date | contents | previous_date | previous_contents | |
|---|---|---|---|---|
| 1114 | 2019-11-26 | 5 | 2018-11-26 | NaN |
YOY = (해당 일자의 콘텐츠 수 - 전년 일자의 콘텐츠 수)/전년 일자의 콘텐츠 수
growth['yoy'] = (growth['contents']-growth['previous_contents'])/growth['previous_contents']
growth.tail()
| date | contents | previous_date | previous_contents | yoy | |
|---|---|---|---|---|---|
| 1709 | 2021-09-21 | 5 | 2020-09-21 | 1.0 | 4.000000 |
| 1710 | 2021-09-22 | 9 | 2020-09-22 | 2.0 | 3.500000 |
| 1711 | 2021-09-23 | 2 | 2020-09-23 | 2.0 | 0.000000 |
| 1712 | 2021-09-24 | 10 | 2020-09-24 | 2.0 | 4.000000 |
| 1713 | 2021-09-25 | 1 | 2020-09-25 | 6.0 | -0.833333 |
rolling()¶
- rolling() 함수를 이용하여 MAU 구하기
netflix titles 데이터를 활용하여 active user 계산이 불가하다. contents 수로 임의로 계산하자.
au = growth[['date', 'contents']].rename({'contents':'dau'}, axis = 1)
au.sample()
| date | dau | |
|---|---|---|
| 1382 | 2020-09-19 | 6 |
rolling() 함수를 이용하면 최근 30일 간의 총합을 구할 수 있다.
au['mau'] = au.rolling(30).sum()
au.head(30)
| date | dau | mau | |
|---|---|---|---|
| 0 | 2008-01-01 | 1 | NaN |
| 1 | 2008-02-04 | 1 | NaN |
| 2 | 2009-05-05 | 1 | NaN |
| 3 | 2009-11-18 | 1 | NaN |
| 4 | 2010-11-01 | 1 | NaN |
| 5 | 2011-05-17 | 1 | NaN |
| 6 | 2011-09-27 | 1 | NaN |
| 7 | 2011-10-01 | 11 | NaN |
| 8 | 2012-02-21 | 1 | NaN |
| 9 | 2012-11-14 | 1 | NaN |
| 10 | 2012-12-01 | 1 | NaN |
| 11 | 2013-03-31 | 1 | NaN |
| 12 | 2013-08-02 | 1 | NaN |
| 13 | 2013-09-01 | 2 | NaN |
| 14 | 2013-10-08 | 1 | NaN |
| 15 | 2013-10-14 | 2 | NaN |
| 16 | 2013-11-01 | 2 | NaN |
| 17 | 2013-12-12 | 1 | NaN |
| 18 | 2013-12-29 | 1 | NaN |
| 19 | 2014-01-17 | 1 | NaN |
| 20 | 2014-01-24 | 1 | NaN |
| 21 | 2014-02-01 | 1 | NaN |
| 22 | 2014-02-16 | 1 | NaN |
| 23 | 2014-04-01 | 1 | NaN |
| 24 | 2014-04-15 | 1 | NaN |
| 25 | 2014-06-15 | 1 | NaN |
| 26 | 2014-07-11 | 1 | NaN |
| 27 | 2014-08-15 | 1 | NaN |
| 28 | 2014-09-26 | 1 | NaN |
| 29 | 2014-10-10 | 1 | 43.0 |