본문 바로가기
Python/빅데이터분석기사(실기)

[빅분기실기]_작업형 1유형 까먹을 것 같은 것 정리하기!(4)_Time_Series

by ssolLEE 2023. 10. 17.
반응형

 

이번 시간은 시계열 데이터(주가 데이터)를 가지고 연습하겠습니다. 

Time_Series

  • Yr_Mo_Dy 컬럼을 datetime64 타입으로 변경하기
    • 직관적인 코드!
    • pd.to_datetime()를 사용합니다.
df['Yr_Mo_Dy'] = pd.to_datetime(df['Yr_Mo_Dy'])
df.info()

  • Yr_Mo_Dy 에 존재하는 연도의 유일값을 모두 출력하기
    • datetime64에서 연도를 보고 싶을 땐 dt.year를 사용합니다. 
    • dt.month, dt.day 등으로 응용할 수 있습니다.
dt.Yr_Mo_Dy.dt.year.unique()

  • Yr_Mo_Dy 에 연도가 2061년 이상의 경우에는 모두 잘못된 데이터이므로, 해당 경우의 값은 100을 빼서 새롭게 날짜를 Yr_Mo_Dy 컬럼에 정의하기
    • import datetime : 날짜 및 시간 작업을 위한 클래스와 함수를 제공하는 모듈을 가져옵니다.
    • 조건문을 이용하여 새로운 연도 값을 계산합니다.
    • 새로운 datetime 객체를 생성합니다. (새로운 연도, 원래의 월, 일)
def fit_year(x):
    import datetime
    year = x.year - 100 if x.year >= 2061 else x.year
    return pd.to_datetime(datetime, date(year, x.month, x.day))

df['Yr_Mo_Dy'] = df['Yr_Mo_Dy'].apply(fit_year)
  • weekday 컬럼을 만들고 요일별로 매핑하기(월 : 0 ~ 일 : 6)
    • dt.weekday는 요일을 정수로 추출합니다. 
    • to_frame()은 Series를 dataframe으로 변환시켜 줍니다. 
df['weekday'] = df.Yr_Mo_Dy.dt.weekday
df['weekday'].to_frame().head(3)

  • weekday 컬럼을 기준으로 주말이면 1, 평일이면 0을 가지는 WeekCheck 컬럼을 만들기
    • 저는 처음에 apply함수를 쓰려고 했는데 막혔습니다. 너무 코드가 길어지더라구요. 
    • map함수를 이용해보겠습니다. 
df['WeekCheck'] = df['weekday'].map(lambda x : 1 if x in [5, 6] else 0)
df['WeekCheck'].to_frame().head(3)

  • 모든 결측치는 컬럼 기준 직전의 값으로 대체하고 첫번째 행에 결측치가 있을 경우 뒤에 있는 값으로 대체하기
    • 결측치를 채우는 코드는 fillna()입니다. 
    • 어떻게 대체할 것인가는 method 옵션 값을 설정합니다. 
    • df.fillna(methon='ffill') : 정방향 채우기 - 누락된 값을 동일한 열에 있는 직전 값으로 바꾸는 것
    • df.fillna(methon='bfill') : 역방향 채우기 - 누락된 값을 동일한 열에 있는 뒤의 값으로 바꾸는 것
df = df.fillna(method = 'ffill').fillna('bfill')
df.isnull().sum()

  • 연도-월을 기준으로 모든 컬럼의 평균값 구하기
    • to_period()는 datetime에서 원하는 시간 간격을 출력할 때 사용합니다. 
    • 'Y' - '2023'
    • 'M' - '2023-10'
    • 'W' - '2023-10-17'
    • 'H' - '2023-10-17 00:00'
df.groupby(df.Yr_Mo_Dy.dt.to_period('M')).mean().head()

  • RPT 컬럼의 값을 일자별 기준으로 1차 차분하기
    • diff()는 한 객체 내에서 열과 열 / 행과 행의 차이를 출력하는 메서드입니다. 
    • df.diff(periods = 1, axis = 1)
      • periods : 비교 간격 지정 (디폴트 +1 : 이전 값과 비교 // -2 : 2칸 후의 값과 비교)
      • axis : 비교 축 지정( 0 : 행끼리, 1 : 열끼리 // 행 - 바로 전 행, 열 - 바로 전 열) 
      • 아래 코드는 컬럼을 지정하였으므로 옵션값에 axis를 입력하지 않았습니다.
df[RPT].diff()

  • RPT와 VAL의 컬럼을 일주일 간격으로 각각 이동평균한 값 구하기
    • 이동평균: 이동하면서 거쳐간 데이터들의 평균값
    • rolling().mean()을 사용합니다. 
    • 아래 캡쳐한 것은 rolling 메서드에 대해 잘 설명해준 블로그(https://amatoroi.tistory.com/23)에서 가져왔습니다. 

출처 : https://amatoroi.tistory.com/23

df[['RPT', 'VAL']].rolling(7).mean()

 

이번에는 서울시 미세먼지 데이터를 이용하겠습니다. 

 

  • (년-월-일:시) 컬럼을 pandas에서 인식할 수 있는 datetime 형태로 변경하기. 서울시의 제공 데이터의 경우 0시가 24시로 표현됨
    • isinstance(x, str) : x가 str인지 알아봅니다. x가 str 이라면 아래의 코드를 수행합니다. 
    • :를 기준으로 문자열을 나누었을 때, 첫 번째 오는건 date, 뒤에 오는건 hour로 지정합니다. 
    • hour가 24라면 00:00:00으로 대체합니다. 그리고 날짜는 다음날로 바뀝니다. 
    • final_date로 조건문의 내용을 다시 적용합니다. 
def change_date(x):
    if isinstance(x, str):
        hour = x.split(':')[1]
        date = x.split(":")[0]

        if hour == '24':
            hour = '00:00:00'
            final_date = pd.to_datetime(date + " " + hour) + pd.Timedelta(days=1)
        else:
            hour = hour + ':00:00'
            final_date = pd.to_datetime(date + " " + hour)
        
        return final_date
    else:
        return x

# Assuming 'data' is your DataFrame
data['(년-월-일:시)'] = data['(년-월-일:시)'].apply(change_date)
data.head()

  • 일자별 영어요일 이름을 dayName 컬럼에 저장하기
    • dt.day_name()
data['dayName'] = data['(년-월-일:시)'].dt.day_name()
data['dayName']
  • 일자별 각 PM10등급의 빈도수 파악하기
data1 = data.groupby(['dayName', 'PM10'], as_index=False).size()
data1.head()

data2 = data1.pivot(index='dayName', columns= 'PM10등급', values = 'size').fillna(0)
data2

  • 시간이 연속적으로 존재하며 결측치가 없는 지 확인하기
    • 시간을 차분했을 때 첫 값은 Nan, 이후 모든 차분값이 동일하면 연속이라 판단한다. 
check = len(data['(년-월-일:시)'].diff().unique())
if check == 2:
    data = True
else:
    data = False

data

  • 오전 10시와 오후 10시(22시)의 PM10의 평균값 구하기
    • dt.hour로 시간을 추출합니다. 
    • 시간을 기준으로 group을 만듭니다. (groupby)
    • 평균을 구하기 위해 mean()을 사용합니다. 
    • iloc[[10, 22], [0]] : 0번쨰 컬럼의 10, 22번째 행을 추출합니다.
Ans = data.groupby(data['(년-월-일:시)'].dt.hour).mean().iloc[[10, 22], [0]]
Ans

  • 데이터를 주 단위로 뽑아서 최소, 최대, 평균, 표준편차 구하기
    • resample() : datetime index를 원하는 주기로 나누어 주는 메서드
Ans = data.resample('W').agg(['min', 'max', 'mean', 'std'])
Ans.head(2)

 

지금까지 시계열 데이터를 다루는 많은 메서드를 연습해보았습니다. 

간단할 것 같지만 막상 하려니 어렵네요. 여러분들은 어떠신가요? 

함께 많이 연습해봅시다.

다음 시간에는 pivot 연습을 하겠습니다.

오늘도 감사합니다.