스파르타 코딩클럽 기초학습
목적
날짜별 기언데이터를 통해 (1)기온변화의 추세, (2)계절적 패턴, (3)이상치를 탐색하여 행후 기온을 예측한다
방법
- 데이터 정제 및 조작 : 결측치 처리, 날짜데이터 변환 등의 전처리 수행
- 기초통계분석 : 연도별, 월별 기온의 평균과 분포분석
- 이동평균 분석 : 장기적인 기온 추세를 파악하기 위해 이동평균 계산
- 상자그림 및 산점도 분석 : 계절적 패턴과 이상치 식별
사용데이터
"Daily Minimum Temperatures in Melbourne"
https://raw.githubusercontent.com/jbrownlee/Datasets/master/daily-min-temperatures.csv
1단계: 데이터로드 및 전처리
-> 데이터를 불러오고 결측치를 제거한다
# 필요한 라이브러리 임포트
import pandas as pd # 데이터를 다루는데 사용되는 라이브러리
import matplotlib.pyplot as plt # 시각화를 위한 라이브러리
import seaborn as sns # Matplotlib을 기반으로 한 시각화 라이브러리
# 데이터 로드
url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/daily-min-temperatures.csv' # 데이터가 저장된 URL -> csv가 아닐경우는?
data = pd.read_csv(url, parse_dates=['Date'], index_col='Date')
- parse_dates : Date열을 데이트타입으로 전환하도록 지정 = pd.datetime
- index_col : 인덱스로 부르고자하는 열 = set_index
# 데이터 확인
print(data.head())
print(data.tail())
# 결측치 확인 및 처리
if data.isnull().values.any(): # 데이터에 결측치(NaN)가 있는지 확인
data.dropna(inplace=True) # 결측치가 있으면 해당 행을 삭제함 -> 너무 많은 경우 다른 값으로 대체
# 데이터 타입 확인
print(data.dtypes)
- isnull() 함수는 각 요소가 결측치인지를 검사 -> values 속성을 통해 결과 얻기 -> any() 함수는 하나 이상의 True 값을 가지면 True를 반환
- => 데이터에 결측치가 있을 경우True를 반환
- dropna() 함수는 결측치를 포함한 행을 제거 -> inplace=True 옵션은 data 데이터프레임이 직접 변경
- => 결측치가 있는 행은 제가된 후 데이터프레임에 바로반영
2단계 : 기초통계 분석
-> 연도별, 월별 평균을 계산한다
# 연도와 월 컬럼 추가
# data인덱스에서 연도를 추출하여 Year의 컬럼의 저장
# data인덱스에서 월을 추출하여 Month의 컬럼의 저장
data['Year'] = data.index.year
data['Month'] = data.index.month
# 연도별 평균 기온 계산
yearly_avg_temp = data.groupby('Year')['Temp'].mean() # 'Year'로 그룹화하여 각 연도별 평균 기온을 계산
# 월별 평균 기온 계산
monthly_avg_temp = data.groupby(['Year', 'Month'])['Temp'].mean().unstack()
# 'Year'와 'Month'로 그룹화하여 각 연도별, 월별 평균 기온을 계산하고,
# unstack() 함수를 사용하여 다중 인덱스에서 월을 열로 변환하여 표 형태로 만듦 -> 중요!
# 연도별 평균 기온 통계 정보 출력
print(yearly_avg_temp.describe())
# 연도별 평균 기온에 대한 통계 정보(평균, 표준편차, 최솟값, 1사분위수, 중위값, 3사분위수, 최댓값)를 출력
3단계 : 이동평균 분석 및 회귀분석을 통한 추세선
-> 이동평균분석을 통해 연도별 기온의 추세를 파악한다
- 이동평균분석이란
과거로부터 현재까지 시계열 자료를 대상으로 일정기간별 이동평균을 계산하고, 이들의 추세를 파악하여 다음 기간을 예측하는 법
시계열 자료에서 계절변동과 불규칙변동을 제거하여 추세변동과 순환변동만 가진 시계열로 변환하는 벙법으로 사용됨
간단하고 쉽게 미래를 예측할 수 있으며, 자료수가 많고 안정된 패턴이 있는 경우 품질이 좋다
뚜렷한 추세가 있거나 불규칙 변동이 심하지 않은 경우 짧은 주기
# 12개월 이동 평균 계산
data['Moving_Avg'] = data['Temp'].rolling(window=365).mean()
# 'Temp' 열을 기준으로 12개월 이동 평균을 계산하여 'Moving_Avg' 열에 저장
# rolling(window=365) 메서드는 이동 평균을 계산하는데 사용되며, 창(window) 크기를 12로 지정하여 365일로 이동 평균을 계산
# 인덱스가 꼭 datetime이어야 함
# 이동 평균 시각화
plt.figure(figsize=(12, 6)) # 시각화 영역의 크기를 설정
plt.plot(data['Moving_Avg'], color='orange', label='12-Month Moving Average') # 이동 평균 데이터를 주황색으로 선 그래프로 플롯
plt.title('12-Month Moving Average of Temperature') # 그래프 제목 설정
plt.xlabel('Date') # x축 레이블 설정
plt.ylabel('Temperature') # y축 레이블 설정
plt.legend() # 라벨을 했으면 꼭 범례 표시
plt.show() # 그래프 출력
data.rolling(window = n).mean()
- 이동평균 주기에 다른 그래프 변화
window = 30 (한달) | window = 120(분기) | window = 730 (2년) |
![]() |
![]() |
![]() |
주기가 길 수록 장기 추세를 확인이 가능하며 단기적으로는 일정한 경향을 알 수 있다
상승과 하강을 반복하지만 상승의 최고점이 점점 높아지는 것을 볼 수 있다
특히, 1988년 이후 더욱 온도가 놀라가고 있다
import numpy as np # 수치 연산을 위한 라이브러리
from sklearn.linear_model import LinearRegression # 선형 회귀 모델 라이브러리 임포트
# 연도별 이동 평균 기온 준비
yearly_moving_avg = data['Moving_Avg'].resample('Y').mean()
# 'Moving_Avg' 열의 연도별 이동 평균을 계산하기 위해 연도(Year)별로 리샘플링하고, 각 연도별 평균값을 계산함
# .resample : 계열 index를 연도 단위의 동일 간격별로 데이터를 뽑으라는 뜻 -> 인덱스가 데이트타입이어야 가능(resample, rolling, year,month), 그룹바이랑 비슷
# 선형 회귀 모델을 사용하여 연도별 평균 추세선 계산
model = LinearRegression().fit(np.arange(len(yearly_moving_avg)).reshape(-1, 1), yearly_moving_avg.values)
# 선형 회귀 모델을 초기화하고, 연도별 이동 평균 기온 데이터에 대해 학습함
# np.arange(len(yearly_moving_avg)).reshape(-1, 1)은 데이터를 피팅하기 위한 형태로 변환함 -> 해석필요
# fit(X_train,y_train)
# 추세선을 위한 예측 값 계산
trend = model.predict(np.arange(len(yearly_moving_avg)).reshape(-1, 1))
# 학습된 모델을 사용하여 각 연도별 추세 값을 예측함
# 이동 평균과 함께 추세선 그리기
plt.figure(figsize=(12, 6)) # 그래프 영역의 크기를 설정함
plt.plot(yearly_moving_avg.index, yearly_moving_avg.values, label='12-Month Moving Average') # 12개월 이동 평균을 플롯함
plt.plot(yearly_moving_avg.index, trend, label='Trend', color='red') # 추세선을 빨간색으로 플롯함
plt.title('12-Month Moving Average with Trend Line') # 그래프 제목 설정
plt.xlabel('Year') # x축 레이블 설정
plt.ylabel('Temperature') # y축 레이블 설정
plt.legend() # 범례 표시
plt.show() # 그래프 출력
model = LinearRegression().fit(X_train,y_train)에 대한 풀이
- LinearRegression()은 선형 회귀 모델을 생성하는 클래스, 이 클래스를 호출하여 모델 객체를 생성
- fit(X_train, y_train)은 생성된 모델 객체에 대해 학습을 수행하는 메서드
- X_train은 학습 데이터로, 모델이 입력으로 사용할 특징 데이터를 나타냄
- y_train은 해당 데이터에 대한 타겟 변수로, 모델이 예측하고자 하는 결과값
np.arange(len(yearly_moving_avg)).reshape(-1, 1)에 대한 풀이
- len(yearly_moving_avg)
의미: yearly_moving_avg의 길이
>>> 10 - np.arange(yearly_moving_avg)
의미: 시작 값부터 끝 값까지 (정해진 간격으로) 숫자들을 생성하여 배열
>>> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - np.arange(len(yearly_moving_avg)).reshape(-1, 1)
의미 : 1차원 array를 2차원으로 배열
>>>array([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
질문
1. x_train에 왜 숫자데이터를 넣었을까?
>[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
2. x_train에 연도를 넣어야 되는 거 아닐까?
연도라는 거는 사람에게 중요한 거지 모델입장에서는 숫자의 증감이 중요함, 1000~2000과 2000~3000은 동일함,
즉 0부터 9까지 증가한다는 것을 나타내기 위해 숫자로 표시한 것
또한 데이터를 가로(컬럼별)로 입력해야 하기 때문(컬럼으로 넣어야 하기 때문)에 1차원 array를 2차원으로 배열
3. 추세선을 회귀분석으로 사용할 필요가 있을까? 각 연도의 평균을 선그래프로 그리는게 아닐까?
trend = model.predict(X_train)에 대한 풀이
predict(X_train) 의미: 학습된 모델(model = LinearRegression())을 사용하여 X_train에 대한 예측값을 1차원 배열로 반환
추세선의 기울기가 양수인 것을 보아 기온이 꾸준히 상승하는 것을 알 수 있다
4단계 : 상자그림 및 산점도 분석
-> 상자그림을 통해 중앙값, 사분위수, 이상치 등을 파악한다
- 상자그림은 통해 확인하는 이상치
IQR(inter quartile range) = 3Q(하위 75%가 되는 지점) - 1Q(하위 25%가 되는 지점)
이상치 = Q1*1.5미만, Q3*1.5초과 범위에 있는 지점
# 월별 기온 분포 상자 그림
# x='Month'는 x축에 월을, y='Temp'는 y축에 기온을 나타냄
sns.boxplot(x='Month', y='Temp', data=data)
# 그래프 제목 설정
plt.title('Box Plot of Temperatures by Month')
plt.show()
유독 1,2월과 11,12월에 이상치가 많이 발생한것을 볼 수 있다.
그러나, 얼마나 많이 발생한 것인지는 알 수 없다
5단계 : 결과 시각화
-> 히트맵을 통해 월별 평균 기온의 변화를 확인한다
plt.figure(figsize=(12, 9))
# 그래프의 크기를 설정함
sns.heatmap(monthly_avg_temp, cmap='coolwarm', annot=True, fmt=".1f")
# seaborn의 heatmap 함수를 사용하여 월별 평균 기온 데이터를 열 지도(heat map)로 시각화함
# monthly_avg_temp는 월별 평균 기온 데이터를 포함하는 DataFrame이며, 각 셀에는 기온 값이 표시됨
# cmap='coolwarm'은 컬러맵을 설정하는데, coolwarm은 차가운 색과 따뜻한 색의 대비를 나타냄
# annot=True는 각 셀에 값의 주석을 추가하라는 의미이며, fmt=".1f"는 주석의 형식을 소수점 첫째 자리까지 표시하라는 의미임
plt.title('Heatmap of Monthly Average Temperatures')
# 그래프의 제목을 설정함
plt.xlabel('Month')
# x축 레이블을 설정함
plt.ylabel('Year')
# y축 레이블을 설정함
plt.show()
# 그래프를 출력함
결론
(1)기온변화의 추세
이동평균과 회귀분석을 통한 추세선을 통해 매년 평균온도가 상승하는 추세가 발견되었다
(2)계절적 패턴
산점도와 상자그림을 통해 1,2월달과 9,11,12월달에 이상치가 발견되었으며,
특별한 기후현상이나 수집의 오류일 수 있다
(3)이상치를 탐색
히트맵을 통해 12~3월이 여름, 6~9월이 경우로 파악되며 강력한 계절패턴이 확인된다.
또한 12과 특히 1,2월에 이상치가 많은것을 보야 여름일때 극단적인더위(데이터 수집오류가 아닐경우)가 많은것이 확인 되었다
'프로젝트' 카테고리의 다른 글
프로젝트 주제 사례 (0) | 2024.03.18 |
---|---|
[주식 프로젝트3] 시계열 데이터 예측하기 (0) | 2024.03.13 |
[주식 프로젝트2] 주식데이터를 통해 기획하기 (0) | 2024.03.13 |
[주식 프로젝트1] 야후 파이낸스 살펴보기 (1) | 2024.02.29 |
[분석프로젝트] 웹 페이지 개선을 통한 A/B테스트: t-test, 시각화 (0) | 2024.02.28 |