이번 프로젝트의 목표는 수업 시간에 배운 내용을 바탕으로 데이터 분석의 pipeline을 처음부터 끝까지 살펴보는 것이다.
프로젝트는 다음과 같이 세 부분으로 구성된다.
분석 결과는 당 Rmd 파일에 코드를 추가하여 knit한 markdown 및 html 파일과 함께 제출한다.
서울특별시 대기오염 측정 자료
서울특별시 대기오염 측정정보 http://data.seoul.go.kr/dataList/OA-15526/S/1/datasetView.do
서울특별시 대기오염 측정소 정보 http://data.seoul.go.kr/dataList/OA-15516/S/1/datasetView.do
서울특별시 대기오염 측정항목 정보 http://data.seoul.go.kr/dataList/OA-15515/S/1/datasetView.do
2016년부터 2020년까지의 서울특별시 행정구역별 대기오염 측정 정보를 다룬다.
서울특별시 대기오염 측정정보
는 2016년부터 2020년까지 5개년간 서울시내 25개 측정소에서 시간대별로 측정한 대기 오염 정보를 연도별로 각 1개의 zip 파일(압축파일)로 담고 있다. 2020년도 압축파일은 월별로 정리된 12개의 csv 파일로 이루어져 있으며, 그외의 압축파일은 하나의 csv 파일로 이루어져 있다.
각 csv 파일의 변수 설명은 다음과 같다.
측정일시
: 측정 날짜와 시각, 예) "20170101000000"
또는 "2017-01-01 00:00:00"
측정소 코드
: 25개의 측정소 코드 (101
– 125
)측정항목 코드
1
: SO2, 3
: NO2, 5
: CO6
: O3, 8
: PM10, 9
: PM2.5평균값
: 해당 시각에 측정된 해당 대기오염 물질 평균 배출량측정기 상태
0
: 정상, 1
: 교정, 2
: 비정상4
: 전원 단절, 8
: 보수중, 9
: 자료이상국가 기준초과 구분
: 0
– 미초과, 1
– 초과지자체 기준초과 구분
: 0
– 미초과, 1
– 초과저장일시
(optional): 저장 날짜와 시각, 예) "20170101000000"
또는 "2017-01-01 00:00:00"
서울특별시 대기오염 측정소 정보
는 1개의 csv 파일로 이루어져 있으며, 아래와 같은 변수를 담고 있다.
측정소 코드
: 서울특별시 대기오염 측정정보
와 같음측정소 이름
: 측정소가 위치한 자치구측정소 주소
: 측정소가 위치한 주소표시 순서
공인코드
서울특별시 대기오염 측정항목 정보
는 1개의 csv 파일로 이루어져 있으며, 아래와 같은 변수를 담고 있다.
측정항목 코드
: 서울특별시 대기오염 측정정보
와 같음측정항목명(줄임명칭)
통신기호
측정단위
화면정렬순서
사용여부
메인화면 표시
소수점자리수
범례-파랑
: 좋음범례-녹색
: 보통범례-노랑
: 나쁨범례-빨강
: 매우나쁨Part 1의 목표는 상기 3종의 대기오염 측정 관련 자료를 relational data로 보고 이들을 연결하여 하나의 데이터프레임으로 만드는 것이다.
참고: R for Data Science Chapter 13
AIR_HOUR_2016.zip
, AIR_HOUR_2017.zip
, AIR_HOUR_2018.zip
, AIR_HOUR_2019.zip
, AIR_HOUR_2020.zip
.서울특별시 대기오염 측정소 정보.csv
.서울특별시 대기오염 측정항목 정보.csv
.data
폴더를 만든다.data
폴더에 넣는다.Hint1: R에서 한글이 포함된 자료를 불러올 때는 인코딩에 주의해야 한다. 한글 인코딩 방식으로는 utf-8
, euc-kr
, cp949
가 있다.
Hint2: 변수명의 오타에 유의하라.
Hint3: 3개의 자료를 모두 제대로 읽었다면, 데이터의 크기는 아래와 같다.
서울특별시 대기오염 측정정보
: 6,516,354 x 7서울특별시 대기오염 측정소 정보
: 25 x 5서울특별시 대기오염 측정항목 정보
: 6 x 12dplyr::*_join()
등을 사용하여 로드한 데이터프레임들을 연결해 하나의 데이터셋으로 만들고 측정일시를 시간순으로 정렬하여라. (20 pts).오염 수준
을 만들고 수행 시간을 출력하여라. (30 pts)Part 2의 목표는 data transform과 visualization을 통해 자료에 대해 직관적인 이해를 도모하는 것이다. 특히 결측치 처리, 이상치 확인, 상관관계 분석 등을 사용할 것이다.
참고:
측정소 코드
, 측정항목 코드
, 국가 기준초과 구분
, 지자체 기준초과 구분
, 측정소 주소
, 표시 순서
, 공인코드
, 통신기호
, 화면 정렬 순서
, 사용여부
, 메인화면 표시
, 소수점 자리 수
, 범례-파랑
, 범례-녹색
, 범례-노랑
, 범례-빨강
지금까지 만든 데이터의 각 변수마다 결측치의 빈도와 비율을 나타내는 테이블을 보여라. (10 pts)
결측치가 있는 변수가 왜 발생하는지 분석하라. (10 pts)
해당 결측치를 처리하여라. (10 pts)
측정기 상태
가 0이 아닐 때는 비정상에 준하는 상태임을 알 수 있다. 그렇다면, 0이 아닌 값을 가지는 측정기 상태
는 어떻게 처리할까? (Total 20 pts)지금까지 만든 데이터의 변수 측정기 상태
에서 각 범주의 빈도와 비율을 나타내는 테이블을 보여라. (10 pts)
위의 테이블과 변수 설명을 고려하여 0이 아닌 값을 가지는 측정기 상태
를 처리하여라. (10 pts)
width = 0.7
). (10 pts)측정일시
를 이용하여 다음의 변수를 새로 정의하라. 년도
, 월
, 일
, 시
(10 pts)subtitle이란 변수를 실제 데이터를 이용하여, “Date: yyyy/mm ~ yyyy/mm”라는 문자열로 정의하라. (문자열 작성시, 실제 데이터의 값을 직접 기입해서는 안된다.) (5 pts)
y_name 이란 변수를 “평균값(\(\mu g/m^3\))”이란 문자열로 정의하라. (5 pts)
월별로 미세먼지(PM2.5, PM10) 평균값 변화의 경향성을 보여주는 꺾은선 그래프를 그린 다음, 그 경향성에 대해 서술하라. (15 pts)
(이 때, 그래프의 세부항목은 다음 지시사항을 따르시오. 그래프의 제목은 “PM10, PM2.5 value for each month”, 부제목은 위에서 정의한 subtitle을 이용하여 작성하라. “월”, y_name을 이용하여 각각 x축과 y축의 이름으로 작성을 하고, x축에는 1~12(정수) 값을 표시하라. 마지막으로 범례도 포함하여 그래프를 작성하라.)
CO | NO2 | SO2 | O3 | PM10 | PM2.5 |
---|---|---|---|---|---|
0.2 | 0.025 | 0.007 | 0.034 | 169 | 89 |
0.3 | 0.012 | 0.003 | 0.078 | 29 | 15 |
0.5 | 0.040 | 0.005 | 0.003 | 47 | 20 |
0.3 | 0.013 | 0.003 | 0.027 | 9 | 6 |
0.3 | 0.024 | 0.007 | 0.036 | 27 | 24 |
0.4 | 0.018 | 0.003 | 0.030 | 19 | 13 |
0.5 | 0.038 | 0.004 | 0.016 | 43 | 23 |
0.4 | 0.012 | 0.003 | 0.030 | 6 | 3 |
0.6 | 0.019 | 0.006 | 0.044 | 41 | 23 |
0.4 | 0.013 | 0.004 | 0.057 | 56 | 35 |
변수 측정일시
, 측정소 이름
, 측정항목
, 평균값
만을 포함한 데이터에서 tidyr::spread()
를 이용하여 위와 같은 데이터를 만들어라. (10 pts) (10개의 데이터를 랜덤추출한 것으로 셀안의 값은 다를 수 있다.)
위에서 만든 데이터에서 결측치가 있는 행들을 삭제하라. (10 pts)
상관관계 행렬을 구해라. (10 pts)
corrplot::corrplot()
을 사용하여 상관관계 plot을 구한 뒤, 대기 오염 물질들이 서로 어떤 관계가 있는지 서술하라. (10 pts)
NO2
와 O3
의 관계를 알아보기 위해 아래의 두 꺾은선 그래프를 그려라. (10 pts)
월
에 따라 NO2
와 O3
의 변화를 나타내는 꺾은선 그래프시
에 따라 NO2
와 O3
의 변화를 나타내는 꺾은선 그래프본 문제에서는 대기오염 물질의 계절에 따른 변화를 모형을 통해 살펴보고자 한다. Part 2, Q3에서의 결과 데이터프레임을 이용하여 다음 물음에 답하여라.
참고:
5년간 이산화질소(NO2) 평균 농도가 가장 큰 구를 찾고, 해당 지역구에 대해 월별로 이산화질소(NO2)의 평균 농도를 계산하여 그림으로 나타내어라. (5 pts)
월별 평균 이산화질소(NO2) 농도를 연도와 계절에 따라 분석하여라. (10 pts)
본 문제에서는 앞선 문제에서 찾은 5년간 이산화질소(NO2) 평균 농도가 가장 큰 지역구의 자료를 이용하여, 다음 날의 이산화질소(NO2)의 일별 평균 농도를 예측하는 모형을 학습하고, 평가하고자 한다.
이산화질소(NO2)의 농도는 이전 날의 이산화질소(NO2)의 농도와 상관관계가 높을 것이라고 예상된다. 이를 기반으로 다음의 모형을 생각할 수 있다.
\[ X_{t} = \beta_{0} + \beta_{1}X_{t-1} + \epsilon_{t} \]
여기서 \(X_{t}\), \(X_{t-1}\)는 각각 \(t\), \(t-1\) 시점의 일별 평균 이산화질소(NO2) 농도이다.
참고로 이를 자기회귀(Auto-Regressive, AR) 모형이라고 한다.
Step 1. 전처리 (14 pts)
해당 지역구의 일별 평균 이산화질소(NO2)의 농도를 계산하여라. 이때, 자료에는 관측이 이루어지지 않은 날짜가 존재한다. 각 관측년도마다 월별 관측일 수를 계산해보고 이를 확인하여라. (7 pts)
위 모형의 학습을 위해서는 \(t\) 시점의 관측치, \(X_t\)와 전날 관측치인 \(X_{t-1}\)이 필요하다. 전날 관측치를 새로운 변수로 저장하여라. 이때, 전날 관측치가 존재하지 않는 경우에는 해당 자료를 제거하여라. (7 pts)
Step 2. 모형의 학습 (21 pts)
모형의 학습 및 성능 평가를 위해 먼저 2016년부터 2019년까지 자료와 2020년의 자료를 각각 훈련용(train) 및 시험용(test) 자료집합으로 분할하여라. 그리고 훈련용 자료와 lm()
함수를 이용하여 위의 모형을 적합하여라. (7 pts)
위에서 학습한 모형을 이용하여, 아래와 같이 잔차도를 그리시오. 잔차도에서 어떤 경향성이 나타나는지 서술하시오. (7 pts)
\(t-1\) 시점의 이산화질소(NO2)의 일별 평균 농도(\(X_{t-1}\))에 계절 변수와 그 교호작용까지 추가하여 아래와 같이 모형을 수정하고자 한다.
\[ \begin{aligned} X_{t} &= \beta_{0} + \beta_{1}X_{t-1} + \sum_{s \in \{\mbox{봄}, \mbox{여름}, \mbox{가을} \}}\beta_{2, s}I(\mbox{측정계절}(t) = s) \\ &\quad + \sum_{s \in \{\mbox{봄}, \mbox{여름}, \mbox{가을} \}}\beta_{3, s}I(\mbox{측정계절}(t) = s)*X_{t-1} + \epsilon_{t} \end{aligned} \]
훈련용 자료를 이용하여 위 모형을 lm()
을 이용하여 학습하고, 직전 문제와 같이 잔차도를 그려보시오. 이전 모형과 같은 경향성이 나타나는가? (7 pts)
Step 3. 모형 성능 평가 (15 pts)
학습한 두 모형의 성능 평가를 위해, 시험용 자료를 이용하고자 한다. 시험용 자료를 이용하여 RMSE (Root Mean Squared Error) 값을 계산하고 비교하여라. 그리고 시험용 자료의 측정날짜별 NO2 농도를 두 모형의 예측값과 함께 한 장의 그래프로 나타내어 비교하여라. 어느 모형이 더 좋다고 할 수 있는가? 그 이유를 이전 문제의 결과를 참조하여 설명하시오. (15 pts)
\[RMSE = \sqrt{\frac{1}{n-1} \sum_{t=2}^n (X_{t} -\hat{X}_{t})^{2}}\]
지금까지 배운 내용을 토대로 미세먼지의 원인을 파악하려고 한다. 미세먼지에 대한 원인은 크게 국내요인과 국외요인이 있다. 이를 더 정확히 파악하기 위하여 2016년부터 2020년까지 매 시간 측정된 서울특별시 각 자치구의 기상 데이터(기온
, 풍향
, 풍속
)를 사용한다. 해당 자료는 기상청 기상자료 개방포털 * 링크1, * 링크2 에서 회원가입후 내려받을 수 있으나, 편의를 위해 개인별 저장소의 data
폴더 안에 kma.zip
이란 이름의 압축파일로 넣어두었다.
Zip 파일 내의 각 csv 파일에 대한 설명은 다음과 같다.
weather2016.csv
, weather2017.csv
, weather2018.csv
, weather2019.csv
, weather2020.csv
: 서울특별시(종로구 제외)의 각 자치구의 기상관측 자료이며, 열 순서대로 측정소 코드
, 측정소 이름
, 측정일시
, 기온
, 풍향
, 풍속
을 나타냄. 이 때, 자치구
중 동작구는 기상청
으로 되어 있으므로, 아래의 자료 정리 과정에서 동작
으로 수정하도록 한다.
weather2016(Jongno).csv
, weather2017(Jongno).csv
, weather2018(Jongno).csv
, weather2019(Jongno).csv
, weather2020(Jongno).csv
: 서울특별시 종로구의 기상관측 자료이며, 열 순서대로 측정소 코드
, 측정소 이름
, 측정일시
, 기온
, 풍속
, 풍향
을 나타냄. 이 때, 자치구
가 종로구가 아닌 서울
로 되어 있으므로, 아래의 자료 정리 과정에서 종로
로 수정하도록 한다.
기온
은 섭씨로 표시되며, 풍속
은 초속 미터, 풍향
은 일반각(360도)으로 표시되는데, 정북향을 기준으로 시계방향으로 회전한 각도를 나타내며 풍속
이 유의미하게 작을 경우 0으로 표시된다. (예를 들어 동풍인 경우는 90, 남풍인 경우는 180, 서풍인 경우는 270, 북풍인 경우는 360, 풍속이 거의 없는 경우는 0)
필요에 따라 라이브러리 MASS
가 사용될 수 있다. 이 경우, select()
라는 이름의 함수가 패키지 MASS
와 dplyr
양쪽에 있으므로 충돌이 발생할 수 있다. 따라서, 데이터프레임에서 원하는 열만 추출하기 위해서는 select()
대신 dplyr::select()
를 사용해야 한다.
Part 1과 마찬가지로 zip 파일의 압축을 명시적으로 해제해서는 안된다.
Part 2, Q3의 결과 데이터프레임과 주어진 자료를 활용하여, 다음과 같은 tibble을 만들어라.
측정일시 | 측정소 이름 | CO | NO2 | O3 | PM10 | PM2.5 | SO2 | 기온 | 풍속 | 풍향 |
---|---|---|---|---|---|---|---|---|---|---|
2016-01-01 | 강남구 | 1.285 | 0.068 | 0.002 | 100 | 67 | 0.006 | 0.7 | 0.9 | 67.2 |
2016-01-01 | 강동구 | 1.170 | 0.050 | 0.002 | 82 | 44 | 0.004 | -1.7 | 1.3 | 101.9 |
2016-01-01 | 강북구 | 1.240 | 0.051 | 0.002 | 79 | 48 | 0.005 | -0.3 | 0.8 | 346.3 |
2016-01-01 | 강서구 | 1.560 | 0.078 | 0.001 | 100 | 76 | 0.007 | 1.0 | 1.1 | 97.1 |
2016-01-01 | 관악구 | 1.770 | 0.069 | 0.003 | 103 | 73 | 0.006 | -3.3 | 2.5 | 201.2 |
2016-01-01 | 광진구 | 1.380 | 0.054 | 0.003 | 98 | 75 | 0.006 | -0.6 | 1.0 | 126.6 |
2016-01-01 | 구로구 | 1.390 | 0.052 | 0.002 | 87 | 84 | 0.008 | -1.4 | 0.0 | 0.0 |
2016-01-01 | 금천구 | 1.200 | 0.058 | 0.005 | 96 | 73 | 0.006 | -1.3 | 0.0 | 0.0 |
2016-01-01 | 노원구 | 1.310 | 0.055 | 0.001 | 76 | 52 | 0.007 | -6.0 | 0.6 | 43.8 |
2016-01-01 | 도봉구 | 1.090 | 0.049 | 0.005 | 71 | 46 | 0.005 | -2.5 | 0.2 | 0.0 |
Hint. Part 2, Q3의 결과 데이터프레임에서 측정일시
, 측정소 이름
, 측정항목
, 평균값
에 해당하는 열을 추출한 다음, 측정항목
의 범주와 이에 대응하는 평균값
열의 값들을 ,측정항목
의 각 범주를 이름으로 하는 여러 개의 열로 변환한다. 이후, 적절히 변형된 자치구별 기상 관측 자료를 측정일시
와 측정소 이름
에 따라 가로로 병합한 후 이를 출력한다. (단, 두 자료 모두 측정일시
와 측정소 이름
이 있는 경우에 한하여 병합한다.)
여기서는 고농도 미세먼지 상황일 때의 풍향 비율을 시각화함으로써 미세먼지의 유입이 풍향과 관계가 있는지 확인하고, 이를 국외 요인과 관계지어 해석하는 것을 목표로 한다.
이를 위하여, Q3-1의 데이터를 이용해 주어진 조건에 맞게 아래와 같은 그림을 재현하고, 해당 그림 결과를 분석 및 문제의 목표에 맞게 해석하여라. 이 때, 풍향은 8방위로 구분하며, 기준은 다음과 같다. (즉, 45도의 단위로 바뀐다는 것을 알 수 있다.)
풍향 범위 |
8방위 |
---|---|
0 초과 22.5 이하 또는 337.5 초과 360.0 이하 | N |
22.5 초과 67.5 이하 | NE |
67.5 초과 112.5 이하 | E |
112.5 초과 157.5 이하 | SE |
157.5 초과 202.5 이하 | S |
202.5 초과 247.5 이하 | SW |
247.5 초과 292.5 이하 | W |
292.5 초과 337.5 이하 | NW |
조건 1: 분석 대상은 고농도 미세먼지 상황이다. 고농도 미세먼지 상황이란, Q3-1의 데이터에서 PM10
의 값은 150을 초과, PM2.5
의 값은 75를 초과하는 경우를 의미한다.
조건 2: Q3-1의 자료에서 PM10
또는 PM2.5
의 값이 결측치이거나, 풍향
의 값이 결측치 또는 0 이하이거나 360 초과인 행은 제거한다.
조건 3: 조건문이나 반복문을 사용하지 않는다.
Hint. geom_polygon
을 이용하라. 이 때 x축의 이름은 넣지 않고 y축의 이름은 Proportion
으로 하라.
NO2
)와 풍향을 통한 미세먼지 원인 분석 (10 pts)여기서는 이산화질소와 미세먼지 농도, 풍향의 관계를 분석하고, 아래와 같은 이산화질소의 특징과 풍향 정보를 이용하여 미세먼지의 요인과 관계지어 해석하는 것을 목표로 한다.
질소산화물은 물질의 특성상 원거리 이동을 못한다. 따라서, 평소 측정지역에서 발생한 초미세먼지수치는 질소산화물수치와 정비례한다. 따라서, 초미세먼지수치를 종속변수로 두고 질소산화물수치를 독립변수를 두어 단순선형회귀분석을 적합하였을 때, 그로부터 얻어지는 표준화된 잔차가 절대값이 큰 경우가 유의미하게 존재하면, 미세먼지 농도가 국내요인만으로 설명될 수 없음을 알 수 있다.
이를 위하여, Q3-1의 자료를 이용해 아래의 단계를 따라 분석을 진행하고 문제의 목표에 맞게 해석하여라.
Step 1: Q3-1의 자료에서 NO2
, PM10
, PM2.5
의 값이 결측치이거나, 풍향
의 값이 결측치 또는 0 이하이거나 360 초과인 행들을 모두 제거하고, 단위를 통일하기 위해 NO2
의 값을 1000배한다.
Step 2 : Q3-2에 주어진 기준에 따라서 풍향
을 8방위로 변환한다.
Step 3 : PM10
을 종속변수로, NO2
를 독립변수로 두어 단순선형회귀 모형을 적합한다. 그로부터 얻어지는 잔차를 표준화하여 PM10
에 덮어 씌우고, PM10
의 값이 2보다 큰 행들만 추출한다. 그리고 풍향
열에 대하여 8방위 풍향별 비율을 계산한다.
Step 4 : PM2.5
을 종속변수로, NO2
를 독립변수로 두어 단순선형회귀 모형을 적합한다. 그로부터 얻어지는 잔차를 표준화하여 PM2.5
에 덮어 씌우고, PM2.5
의 값이 2보다 큰 행들만 추출한다. 그리고 풍향
열에 대하여 8방위 풍향별 비율을 계산한다.