코딩 실력이 너무 퇴화된 것 같아서.. 조금씩 연습해보려고 한다!
https://gils-lab.tistory.com/118
[데이터 코딩테스트 대비 #1] 미세먼지 농도
문제 PM10_seoul.csv는 12월 1일 1시부터 8일 24시까지 한 시간마다 측정한 미세먼지 농도(PM-10) 데이터이다. date 컬럼은 측정 시간(YYYY-MM-DD:HH)를 나타내며, PM-10은 미세먼지 농도를 나타낸다. 이 데이터
gils-lab.tistory.com
이 분 블로그를 참고해서 풀어보았다.
문제
PM10_seoul.csv는 12월 1일 1시부터 8일 24시까지 한시간마다 측정한 미세먼지 농도(PM-10) 데이터이다.
date 컬럼은 측정 시간(YYYY-MM-DD:HH)를 나타내며, PM-10은 미세먼지 농도를 나타낸다.
총 4개의 문제가 있다.
(1) 시간에 따른 미세먼지 농도를 적절한 그래프로 시각화 하세요. 단 x축 이름은 date, y축 이름은 PM-10이어야 합니다.
import pandas as pd
import numpy as np
seoul = pd.read_csv('./PM10_seoul.csv')
seoul
date | PM-10 |
2022-12-08:24 | 22.0 |
2022-12-08:23 | 22.0 |
2022-12-08:22 | 25.0 |
2022-12-08:21 | 23.0 |
2022-12-08:20 | 20.0 |
... | ... |
2022-12-01:02 | 12.0 |
2022-12-01:01 | 15.0 |
NaN | NaN |
NaN | NaN |
NaN | NaN |
195 rows × 2 columns
일단 밑에 결측치가 보여서 결측치를 처리해주었다. 결측치가 3개밖에 안되어서 그냥 삭제해주었는데, 결측치를 처리하는데에는 2가지 방법이 있다.
결측치 처리방법
1. 결측치 제거 (삭제) - 선택한 방법
# 결측치가 있는 모든 행 삭제
seoul = seoul.dropna()
seoul
* 결측치가 있는 모든 열을 제거하려면 .dropna(axis=1)을 해주면 된다.
2. 결측치 대체(채우기)
-> 결측치를 특정 값으로 대체한다. (ex. 평균, 중앙값, 최빈값 등)
# 결측치를 평균값으로 대체
seoul_filled = seoul.fillna(seoul.mean())
# 결측치를 중앙값으로 대체
seoul_filled_median = seoul.fillna(seoul.median())
# 결측치를 최빈값으로 대체
seoul_filled_mode = seoul.fillna(seoul.mode().iloc[0]
# iloc[0]이면 데이터 프레임의 첫번째 행을 선택하는 것
그리고 시간에 따른 미세먼지 농도를 그래프로 그려야하는데 오름차순으로 정리되어 있지 않아서,
'date'를 기준으로 하여 오름차순 정리를 해주었다.
seoul = seoul.sort_values(by='date')
seoul
date | PM-10 |
2022-12-01:01 | 15.0 |
2022-12-01:02 | 12.0 |
2022-12-01:03 | 14.0 |
2022-12-01:04 | 15.0 |
2022-12-01:05 | 15.0 |
... | ... |
2022-12-08:20 | 20.0 |
2022-12-08:21 | 23.0 |
2022-12-08:22 | 25.0 |
2022-12-08:23 | 22.0 |
2022-12-08:24 | 22.0 |
192 rows × 2 columns
from matplotlib import pyplot as plt
x = range(len(seoul['date'])) # 그냥 datetime 형식이 아니라 시간이 추가된 형태라서 이렇게 하는 것 같다.
y = seoul['PM-10']
plt.plot(x,y)
plt.xlabel('date')
plt.ylabel('PM-10')
plt.show()
수많은 date를 x 축에 한번에 표시할 때, range(len())을 쓰는 경우를 처음 봤는데,
len(seoul['date'])
#192
range(len(seoul['date']))
#range(0,192)
이라서 저렇게 값이 나올 수 있는 것 같다.
(2) 시간대별 평균 미세먼지 농도를 계산하세요. 즉 t시 (t=1,2,....24)의 평균 농도를 구하시오.
이 문제를 풀기 위해서는 일단 date 데이터에서 시간 부분을 추출해야한다.
나는 split를 사용 했다.
seoul['time'] = seoul['date'].str.split(':', expand = True).iloc[:,1]
seoul['time']
191 01
190 02
189 03
188 04
187 05
..
4 20
3 21
2 22
1 23
0 24
Name: time, Length: 192, dtype: object
* split 함수 안에 expand=True 옵션을 지정해주면, 데이터를 split한 결과를 데이터프레임으로 확장해준다.
-> 모든 열 값에 대해 데이터를 처리하고 싶을 때 이렇게 expand를 지정해주면 된다.
* iloc vs. loc
- iloc: pandas 데이터프레임에서 정수 위치 기반으로 데이터를 선택하는 데 사용되는 인덱서이다. 행과 열의 인덱서를 사용하여 특정 부분의 데이터를 선택할 수 있다. (iloc 이니까 index location이라 생각하자)
ex) iloc[:,1] -> ':' 는 모든 행을 선택, 1은 두번째 열 (인덱스가 1인 열)을 선택함.
=> iloc[:,1]은 데이터프레임의 모든 행에서 두 번째 열의 데이터를 선택함
seoul['date'].str.split(':', expand=True)
이렇게 나오니까, 여기서 두번째 열만 선택함으로써 '시간'에 해당하는 값만 빼준것임.
- loc
iloc이 정수 인덱스를 사용하여 위치 기반으로 데이터를 선택했다면,
loc은 레이블을 사용하여 명시적으로 데이터를 선택한다.
ex)
import pandas as pd
# 예시 데이터프레임 생성
data = {'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}
df = pd.DataFrame(data, index=['one', 'two', 'three'])
# iloc 사용 (정수 인덱스)
print(df.iloc[0, 1]) # 출력: 4, 첫 번째 행과 두 번째 열
print(df.iloc[:, 0]) # 출력: one 1, two 2, three 3, Name: A
# loc 사용 (레이블 인덱스)
print(df.loc['one', 'B']) # 출력: 4, 'one' 행과 'B' 열
print(df.loc[:, 'A']) # 출력: one 1, two 2, three 3, Name: A
다시 돌아와서, time 열에 시간만 뽑아서 저장해줬다면, groupby를 이용해서 평균을 계산해주면 된다.
seoul.groupby('time')['PM-10'].mean()
time
01 25.875
02 22.000
03 21.000
04 21.000
05 21.375
06 21.375
07 20.250
08 22.375
09 23.125
10 22.750
11 27.000
12 25.125
13 25.250
14 28.000
15 24.500
16 24.500
17 26.500
18 25.500
19 25.125
20 27.000
21 28.125
22 28.125
23 27.250
24 26.625
Name: PM-10, dtype: float64
(3) 시점 t의 미세먼지 농도를 시점 t-1, t-2, t-3, t-4의 농도를 이용하여 예측하는 모델을 학습하기 위한 데이터를 구성하세요. 예를 들어, 8일 24시의 미세먼지 농도를 8일 20-23시의 농도로 예측할 수 있도록 구성합니다.
shift 함수를 사용하면 간편하게 할 수 있다.
shift 함수 : 데이터프레임이나 시리즈의 데이터를 일정한 시점만큼 이동시키는 데 사용됨.
- 양수 값이 주어지면 데이터를 앞으로 이동시킴 (이전 시점의 값이 현재 시점으로 이동함) -> 이전 시점 구하려면 양수값. (입력한 기간만큼 데이터를 앞으로 이동시키므로, 양수를 넣으면 이전 시점의 값을 현재 시점으로 이동시킬 수 있음 ex. shitf(1)은 데이터를 1단위 앞으로 이동시켜서 이전 시점의 값을 현재 시점에 맞춤)
- 음수 값이 주어지면 데이터를 뒤로 이동시킴
shift 함수를 쓰면 lag 변수를 쉽게 만들 수 있다.
(lag 변수는 시간차이를 따른 독립변수의 효과를 보기 위해 연구자가 원하는 단위의 시간(월, 분기, 연 등)만큼 종속변수 대비 과거 시점의 데이터를 추출해낸 변수다.)
-> 원하는 변수명 뒤에 .shift(원하는 lag단위) 입력
# k시간 전 농도 부착
for k in range(1,5):
seoul['PM-10_'+ k] = seoul['PM-10'].shift(k)
# shift 하면서 생기는 결측치 제거
seoul.dropna(inplace=True)
seoul
# 모델링에 활용하지 않는 변수 제거
seoul = seoul.drop(['date', 'time'], axis=1)
# 열(변수) 제거하는 거니까 axis=1 사용
seoul
(4) PM-10 컬럼을 기준으로 특징과 라벨을 분리하고 이를 바탕으로 모델을 학습합니다.
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error
X = seoul.drop('PM-10', axis = 1)
y = seoul['PM-10']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 100)
model = LinearRegression()
model.fit(X_train, y_train)
pred = model.predict(X_test)
r2 = r2_score(pred, y_test)
mse = mean_squared_error(pred, y_test)
print(f'R^2 score : {r2}')
print(f'Mean Squared Error : {mse}')
R^2 score:0.8164358609512208
Mean Squared Error:15.113531751879977
'데이터 분석' 카테고리의 다른 글
[데이터분석 코딩연습 #2] 교통사고 통계 (0) | 2024.08.12 |
---|