파이썬 단변량 분석(EDA)
이전 포스팅에서는 폴더 내 데이터를 한번에 불러오고 병합하는 방법을 몰라서 2022년 2월 데이터만 사용했었음...
이번 포스팅에서는 2021년 1월 ~ 2021년 12월 대기정보 데이터 사용
** 데이터 다운로드
에어코리아 → 통계정보 → 최종확정 측정자료 조회 → 확정자료 다운로드 → 2021년 데이터 다운로드
https://www.airkorea.or.kr/web/last_amb_hour_data?pMENU_NO=123
1. 라이브러리
# 라이브러리
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# warnings 무시
import warnings
warnings.filterwarnings('ignore')
# 폰트설정
plt.rcParams['font.family'] = 'Malgun Gothic'
plt.rcParams['axes.unicode_minus'] = False
# 그래프 선명
%config InlineBackend.figure_format = 'retina'
2. 데이터 불러오기
# 폴더내 파일명 불러오고 데이터 병합 - glob()
import pandas as pd
from glob import glob
file_names = glob("경로/2021*.xlsx") # 2021*.xlsx : 2021문자로 시작하는 xlsx 파일
total = pd.DataFrame()
for file_name in file_names:
temp = pd.read_excel(file_name)
total = pd.concat([total, temp])
=> 데이터가 커서 불러오는 것만 10분 정도 소요 됨(코드는 길어지지만 하나씩 불러오는게 더 빠른 것 같음......)
** glob은 파일명을 불러온 후, for()문을 사용하여 짧은 코드로 데이터 병합을 할 수 있다.
3. 인천시 내 측정소명 기준인 air 데이터프레임 생성
# 인천 데이터를 뽑아서 incheon_air 데이터프레임 생성
incheon_air = total[total['지역'].str.contains('인천')]
# air 데이터프레임으로 복사
air = incheon_air.copy()
# 불필요한 컬럼 삭제
drop_col = ['Unnamed: 0', '지역', '망', '측정소코드', '주소']
air.drop(drop_col, axis=1, inplace=True)
# 인덱스 초기화
air.reset_index(drop=True, inplace=True)
air.head()
4. 측정일시
1) datetime 변환 - 파이썬 int타입_datetime타입으로 변환 (tistory.com) 참고
2) 슬라이싱으로 컬럼 생성 - 여기서는 이 방법으로 진행
# 측정일시 컬럼 문자열로 변환
air['측정일시'] = air['측정일시'].astype('str')
# 측정날짜 컬럼 데이터 중 7번째까지 측정일시, 8번째부터 끝까지는 측정시간 컬럼 생성
air['측정날짜'] = air['측정일시'].str[:8]
air['측정시간'] = air['측정일시'].str[8:]
# 측정날짜 컬럼 datetime타입으로 변환
air['측정날짜'] = pd.to_datetime(air['측정날짜'])
display(air.head())
air.info()
=> datetime 타입인 측정날짜 컬럼과 object인 측정시간 컬럼 생성함.
5. 인천광역시 측정날짜별 데이터
col = ['SO2', 'CO', 'O3', 'NO2', 'PM10', 'PM25']
air_incheon = air.groupby('측정날짜', as_index=False)[col].mean()
=> 측정날짜를 기준으로 각 측정소의 대기정보 평균으로 인천시 대기정보 평균 데이터프레임 생성
- 데이터 확인
air_incheon.head()
air_incheon.info()
결측값 없고 데이터도 잘 가져왔다.
데이터 준비하는 것만 오래 걸렸다... (측정소별 하려다 너무 길어질 것 같아서 인천으로 그룹화 해버림...)
- 기초통계량 : describe()
# 기초통계량
air_incheon.describe()
=> 데이터 수, 평균, 표준편차, 최솟값, 1사분위수, 2사분위수, 3사분위수, 최댓값 순서로 정보를 알 수 있음.
- 히스토그램 : plt.hist()
pm25_hist = plt.hist(air_incheon['PM25'], bins=10, edgecolor='gray')
plt.xlabel('PM25')
plt.ylabel('Count')
plt.show()
print(pm25_hist)
print('-'*50)
print('구간값 : ', pm25_hist[1])
print('빈도수 : ', pm25_hist[0])
=> 각 구간값 별 빈도수 출력해서 확인
=> PM25는 30아래로 분포가 몰려 있음
- 밀도함수 그래프 : kdeplot()
sns.kdeplot(air_incheon['PM25'])
plt.show()
=> 많은 데이터가 0~50에 분포한다.
- 히스토그램+밀도함수그래프 : histplot(kde=True)
# 히스토그램과 밀도함수그래프 같이 그리기
sns.histplot(incheon_air['PM25'], bins=10, kde=True)
plt.show()
=> 히스토그램과 밀도함수 그래프를 함께 그림
- 박스플롯 : boxplot
# 박스플롯
sns.boxplot(x=air_incheon['PM25'])
plt.grid()
plt.show()
=> 최솟값, 1사분위수, 2사분위수(중위수), 3사분위수, 최댓값 확인할 수 있다.
=> 박스플롯으로 이상치 확인가능
- 선그래프 : plot()
plt.figure(figsize=(10,10))
plt.subplot(4,1,1)
plt.plot(air_incheon['측정날짜'], air_incheon['PM10'], label='PM10')
plt.plot(air_incheon['측정날짜'], air_incheon['PM25'], label='PM25')
plt.legend()
plt.subplot(4,1,2)
plt.plot(air_incheon['측정날짜'], air_incheon['CO'], label='CO')
plt.legend()
plt.subplot(4,1,3)
plt.plot(air_incheon['측정날짜'], air_incheon['O3'], label='O3')
plt.plot(air_incheon['측정날짜'], air_incheon['NO2'], label='NO2')
plt.legend()
plt.subplot(4,1,4)
plt.plot(air_incheon['측정날짜'], air_incheon['SO2'], label='SO2')
plt.legend()
plt.show()
=> 측정날짜별 대기측정정보를 선그래프로 확인
=> 3월, 5월에 PM10 수치가 급격하게 높아진 날짜가 있음. 확인할 필요 있음
=> CO는 겨울에 높은편임
=> O3는 여름에 높아지는 것을 볼 수 있음. NO2는 겨울에 다른 계절보다 높은 것을 확인할 수 있음
=> 4월 SO2 수치가 급격하게 높아졌고, 10월 이후 높아지는 추세를 보임
6. PM25 위험도에 따른 기준으로 범주형으로 변환
** 참고 : 환경부 - 미세먼지(PM2.5) 환경기준 미국 일본 수준으로 강화 (me.go.kr)
0~15:좋음, ~35:보통, ~75:나쁨, ~∞:매우나쁨
pm25_bin = [0,15,35,75,np.inf]
pm25_label = ['좋음', '보통', '나쁨', '매우나쁨']
air_incheon['pm25_standard'] = pd.cut(air_incheon['PM25'], bins=pm25_bin, labels=pm25_label)
air_incheon['pm25_standard'].value_counts()
- 막대그래프 : countplot()
sns.countplot(x='pm25_standard', data=air_incheon)
plt.show()
- 파이차트 : pie()
temp = air_incheon['pm25_standard'].value_counts()
plt.pie(temp.values, labels = temp.index, autopct = '%.2f%%')
plt.show()
# 파이차트 옵션
plt.pie(temp.values, labels = temp.index, autopct = '%.2f%%',
startangle=90, counterclock=False,
explode = [0.05, 0.05, 0.05, 0.05], shadow=True)
plt.show()
365일 중에 [보통 171일, 좋음 155일, 나쁨 34일, 매우나쁨 5일]임을 확인할 수 있다.
- 2021년에는 초미세먼지 PM25가 좋음과 보통인 날이 90%이상이다.