mise_23

Author

hyunjhin Lee

2018년 서울 미세먼지 데이터 시각화를 위한 준비 과정 기록

(Tidyverse, Lubridate, for 사용 예제 포함)

사용한 데이터 :

AIR_HOUR_10YEAR.csv: 10년간 미세먼지 측정 정보 (2008~2018)

AIR_LOCATION.csv : 미세먼지 측정소 정보

AIR_HOUR_2018.csv: 2018년 미세먼지 측정 정보

CLIMATE_HOUR_2018.csv : 108번 측정소의 2018년 날씨 정보

1. 데이터 불러오기

첫 행에 열이름이 깨져있어서 첫행빼고, 열 이름 없이 import, 열 이름을 벡터로 추가함.

Code
library(tidyverse)
── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
✔ ggplot2 3.4.0      ✔ purrr   1.0.0 
✔ tibble  3.1.8      ✔ dplyr   1.0.10
✔ tidyr   1.2.1      ✔ stringr 1.5.0 
✔ readr   2.1.4      ✔ forcats 0.5.2 
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
Code
air_hour_10y <-read_csv("AIR_HOUR_10YEAR.csv", skip = 1,col_names = FALSE)
Rows: 2150195 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
dbl  (3): X2, X3, X4
dttm (1): X1

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Code
head(air_hour_10y)
Code
colnames(air_hour_10y, do.NULL = TRUE)
[1] "X1" "X2" "X3" "X4"
Code
x <- c("time","place","pm10","pm2.5") #add col name
colnames(air_hour_10y) <-x 
tail(air_hour_10y)

air_hour_10y의 데이터 구조를 확인

Code
str(air_hour_10y)
spc_tbl_ [2,150,195 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ time : POSIXct[1:2150195], format: "2009-01-01 00:00:00" "2009-01-01 01:00:00" ...
 $ place: num [1:2150195] 101 101 101 101 101 101 101 101 101 101 ...
 $ pm10 : num [1:2150195] 38 44 29 31 34 38 33 42 48 32 ...
 $ pm2.5: num [1:2150195] 8 10 24 17 15 8 26 18 17 13 ...
 - attr(*, "spec")=
  .. cols(
  ..   X1 = col_datetime(format = ""),
  ..   X2 = col_double(),
  ..   X3 = col_double(),
  ..   X4 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
summary(air_hour_10y)
      time                            place          pm10       
 Min.   :2009-01-01 00:00:00.00   Min.   :101   Min.   :   1.0  
 1st Qu.:2011-07-12 18:30:00.00   1st Qu.:107   1st Qu.:  25.0  
 Median :2014-01-03 13:00:00.00   Median :113   Median :  39.0  
 Mean   :2014-01-03 18:35:19.03   Mean   :113   Mean   :  45.8  
 3rd Qu.:2016-06-30 02:00:00.00   3rd Qu.:119   3rd Qu.:  58.0  
 Max.   :2018-12-31 23:00:00.00   Max.   :125   Max.   :1354.0  
     pm2.5       
 Min.   :  0.00  
 1st Qu.: 13.00  
 Median : 21.00  
 Mean   : 24.28  
 3rd Qu.: 31.00  
 Max.   :250.00  

나머지 파일들 불러오기

Code
AIR_HOUR_2018 <- read_csv("AIR_HOUR_2018.csv")#18년 측정 정보 
Rows: 1314000 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (1): 실시간 수신 구분
dbl  (6): 측정소 코드, 측정항목 코드, 평균값, 측정기 상태, 국가 기준초과 구분, 지자체 지군초과 구분...
dttm (1): 측정일시

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Code
air_hour_2018 <-AIR_HOUR_2018 #소문자 변경 
str(air_hour_2018)
spc_tbl_ [1,314,000 × 8] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ 측정일시            : POSIXct[1:1314000], format: "2018-01-01 00:00:00" "2018-01-01 00:00:00" ...
 $ 측정소 코드         : num [1:1314000] 101 101 101 101 101 101 102 102 102 102 ...
 $ 측정항목 코드       : num [1:1314000] 1 3 5 6 8 9 1 3 5 6 ...
 $ 평균값              : num [1:1314000] 0.006 0.021 0.4 0.022 29 17 0.004 0.02 0.5 0.02 ...
 $ 측정기 상태         : num [1:1314000] 0 0 0 0 0 0 0 0 0 0 ...
 $ 실시간 수신 구분    : chr [1:1314000] "R" "R" "R" "R" ...
 $ 국가 기준초과 구분  : num [1:1314000] 0 0 0 0 0 0 0 0 0 0 ...
 $ 지자체 지군초과 구분: num [1:1314000] 0 0 0 0 0 0 0 0 0 0 ...
 - attr(*, "spec")=
  .. cols(
  ..   측정일시 = col_datetime(format = ""),
  ..   `측정소 코드` = col_double(),
  ..   `측정항목 코드` = col_double(),
  ..   평균값 = col_double(),
  ..   `측정기 상태` = col_double(),
  ..   `실시간 수신 구분` = col_character(),
  ..   `국가 기준초과 구분` = col_double(),
  ..   `지자체 지군초과 구분` = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
air_location <-read_csv("AIR_LOCATION.csv") #측정소 정보 
Rows: 42 Columns: 5
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): 측정소 이름, 측정소 주소
dbl (3): 측정소 코드, 표시 순서, 공인코드

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Code
str(air_location)
spc_tbl_ [42 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ 측정소 코드: num [1:42] 101 102 103 104 105 106 107 108 109 110 ...
 $ 측정소 이름: chr [1:42] "종로구" "중구" "용산구" "은평구" ...
 $ 측정소 주소: chr [1:42] "종로구 종로35가길 19 (종로5.6가동 주민센터)" "중구 덕수궁길 15 (시청서소문별관 3동)" "용산구 한남대로 136 (서울특별시중부기술교육원)" "은평구 진흥로 215 (한국환경산업기술원)" ...
 $ 표시 순서  : num [1:42] 1 2 3 4 5 6 7 8 9 10 ...
 $ 공인코드   : num [1:42] 111123 111121 111131 111181 111191 ...
 - attr(*, "spec")=
  .. cols(
  ..   `측정소 코드` = col_double(),
  ..   `측정소 이름` = col_character(),
  ..   `측정소 주소` = col_character(),
  ..   `표시 순서` = col_double(),
  ..   공인코드 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
climate_2018 <-read_csv("CLIMATE_HOUR_2018.csv", skip = 1,col_names = FALSE)
Rows: 8760 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): X2
dbl (5): X1, X3, X4, X5, X6

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Code
y <-c("지점","일시","기온","풍속","풍향","습도") #열이름 지정 
colnames(climate_2018) <-y
str(climate_2018)
spc_tbl_ [8,760 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ 지점: num [1:8760] 108 108 108 108 108 108 108 108 108 108 ...
 $ 일시: chr [1:8760] "2018-01-01 0:00" "2018-01-01 1:00" "2018-01-01 2:00" "2018-01-01 3:00" ...
 $ 기온: num [1:8760] -3.2 -3.3 -3.7 -4 -4.2 -4.4 -4.5 -4.7 -5 -4.3 ...
 $ 풍속: num [1:8760] 0.5 0.7 0.9 1 1.1 0.8 1.1 1.1 1 0.7 ...
 $ 풍향: num [1:8760] 110 360 270 290 290 290 320 290 290 290 ...
 $ 습도: num [1:8760] 40 41 42 44 53 54 51 56 55 39 ...
 - attr(*, "spec")=
  .. cols(
  ..   X1 = col_double(),
  ..   X2 = col_character(),
  ..   X3 = col_double(),
  ..   X4 = col_double(),
  ..   X5 = col_double(),
  ..   X6 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
head(climate_2018)

2. 데이터 내용 확인 후, 필요한 내용(열)만 선택 편집

Code
colnames(air_hour_10y) #"time"  "plece"(101-125) "pm10"  "pm2.5" 
[1] "time"  "place" "pm10"  "pm2.5"
Code
colnames(air_hour_2018)
[1] "측정일시"             "측정소 코드"          "측정항목 코드"       
[4] "평균값"               "측정기 상태"          "실시간 수신 구분"    
[7] "국가 기준초과 구분"   "지자체 지군초과 구분"
Code
#"측정일시" "측정소 코드"  "측정항목 코드" "평균값" "측정기 상태" "실시간 수신 구분"  "국가 기준초과 구분" "지자체 지군초과 구분"
colnames(air_location) #"측정소 코드" "측정소 이름" "측정소 주소" "표시 순서" "공인코드"   
[1] "측정소 코드" "측정소 이름" "측정소 주소" "표시 순서"   "공인코드"   
Code
colnames(climate_2018) # "지점" "일시" "기온" "풍속" "풍향" "습도", 108번 장소 
[1] "지점" "일시" "기온" "풍속" "풍향" "습도"
Code
str(climate_2018) # 일시는 date-time으로, 지점은 모두 108번 지점, 8760개, 결측값 없음
spc_tbl_ [8,760 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ 지점: num [1:8760] 108 108 108 108 108 108 108 108 108 108 ...
 $ 일시: chr [1:8760] "2018-01-01 0:00" "2018-01-01 1:00" "2018-01-01 2:00" "2018-01-01 3:00" ...
 $ 기온: num [1:8760] -3.2 -3.3 -3.7 -4 -4.2 -4.4 -4.5 -4.7 -5 -4.3 ...
 $ 풍속: num [1:8760] 0.5 0.7 0.9 1 1.1 0.8 1.1 1.1 1 0.7 ...
 $ 풍향: num [1:8760] 110 360 270 290 290 290 320 290 290 290 ...
 $ 습도: num [1:8760] 40 41 42 44 53 54 51 56 55 39 ...
 - attr(*, "spec")=
  .. cols(
  ..   X1 = col_double(),
  ..   X2 = col_character(),
  ..   X3 = col_double(),
  ..   X4 = col_double(),
  ..   X5 = col_double(),
  ..   X6 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
climate_2018$일시<-as.POSIXct(climate_2018$일시) 
str(climate_2018)
spc_tbl_ [8,760 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ 지점: num [1:8760] 108 108 108 108 108 108 108 108 108 108 ...
 $ 일시: POSIXct[1:8760], format: "2018-01-01 00:00:00" "2018-01-01 01:00:00" ...
 $ 기온: num [1:8760] -3.2 -3.3 -3.7 -4 -4.2 -4.4 -4.5 -4.7 -5 -4.3 ...
 $ 풍속: num [1:8760] 0.5 0.7 0.9 1 1.1 0.8 1.1 1.1 1 0.7 ...
 $ 풍향: num [1:8760] 110 360 270 290 290 290 320 290 290 290 ...
 $ 습도: num [1:8760] 40 41 42 44 53 54 51 56 55 39 ...
 - attr(*, "spec")=
  .. cols(
  ..   X1 = col_double(),
  ..   X2 = col_character(),
  ..   X3 = col_double(),
  ..   X4 = col_double(),
  ..   X5 = col_double(),
  ..   X6 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
head(climate_2018)

열이름 띄어쓰기 수정, 필요 열만 선별, 팩터형 변형

Code
library(forcats)
colnames(air_hour_2018) <-c("측정일시", "측정소코드",  "측정항목코드" ,"평균값" ,"측정기상태", "실시간수신구분" , "국가기준초과구분", "지자체지군초과구분")
##열 항목에 한글 띄어 쓰기 없엠 
air_hour_2018 <- select(air_hour_2018, 측정일시, 측정소코드, 측정항목코드, 평균값,측정기상태)
air_hour_2018$측정소코드 <- as.factor(air_hour_2018$측정소코드) #팩터형 변환
air_hour_2018$측정항목코드 <- as.factor(air_hour_2018$측정항목코드)
air_hour_2018$측정기상태 <-as.factor(air_hour_2018$측정기상태)
str(air_hour_2018)  
tibble [1,314,000 × 5] (S3: tbl_df/tbl/data.frame)
 $ 측정일시    : POSIXct[1:1314000], format: "2018-01-01 00:00:00" "2018-01-01 00:00:00" ...
 $ 측정소코드  : Factor w/ 25 levels "101","102","103",..: 1 1 1 1 1 1 2 2 2 2 ...
 $ 측정항목코드: Factor w/ 6 levels "1","3","5","6",..: 1 2 3 4 5 6 1 2 3 4 ...
 $ 평균값      : num [1:1314000] 0.006 0.021 0.4 0.022 29 17 0.004 0.02 0.5 0.02 ...
 $ 측정기상태  : Factor w/ 6 levels "0","1","2","4",..: 1 1 1 1 1 1 1 1 1 1 ...

air_hour_2018을 측정기 상태 정상(상태 0), 측정 항목pm10(코드 8), pm2.5(코드 9)만 추출, 측정항목 코드를 열구분 (pm 10, pm2.5) 으로 변형 (spread 사용)

Code
air_hour_18n <- filter(air_hour_2018,측정항목코드==8 |측정항목코드==9)
air_hour_18n <- filter(air_hour_18n,측정기상태==0 )
head(air_hour_18n, n=3)
Code
air_hour_18n <-select(air_hour_18n, 측정일시, 측정소코드, 측정항목코드, 평균값)
air_hour_18n <- spread(air_hour_18n, key=측정항목코드, value = 평균값)
head(air_hour_18n)
Code
colnames(air_hour_18n) <-c("time", "place",  "pm10" ,"pm2.5")
head(air_hour_18n) ##air_hour_10y와 같은 형식

결측값 없에고, 측정소 기준으로 정렬, 측정소 101 정렬 내용 확인 (for문 사용)

Code
air_hour_18n <- arrange(air_hour_18n, place, na.rm=TRUE)  #측정소 별로 정렬 
sum(is.na(air_hour_18n)) #결측 없음 확인 
[1] 4850
Code
air_hour_18n <-na.omit(air_hour_18n) #결측값 있으면 제거 
air_hour_18n$place <-as.character(air_hour_18n$place)
j<-0
i<-1
for(i in 1:nrow(air_hour_18n)){
  ifelse ((air_hour_18n$place[i] == "102"),  break, j<-i) #ifelse(x>1, x*2, x)
  } 
j #101번 측정소 끝은? 8595
[1] 8595
Code
print(air_hour_18n[8596,]) ##102번 첫 행의 내용? 
# A tibble: 1 × 4
  time                place  pm10 pm2.5
  <dttm>              <chr> <dbl> <dbl>
1 2018-01-01 00:00:00 102      34    19
Code
str(air_hour_18n) ###209785 row
tibble [209,785 × 4] (S3: tbl_df/tbl/data.frame)
 $ time : POSIXct[1:209785], format: "2018-01-01 00:00:00" "2018-01-01 01:00:00" ...
 $ place: chr [1:209785] "101" "101" "101" "101" ...
 $ pm10 : num [1:209785] 29 27 30 28 28 32 29 29 31 26 ...
 $ pm2.5: num [1:209785] 17 13 13 14 15 15 16 16 16 11 ...
 - attr(*, "na.action")= 'omit' Named int [1:4850] 2020 2334 2680 2681 2682 2686 2688 4285 4349 4380 ...
  ..- attr(*, "names")= chr [1:4850] "2020" "2334" "2680" "2681" ...
Code
air_hour_18n$place <-as.factor(air_hour_18n$place)

3. climate_2018에 풍향명 추가, 결측 제거, 지점명 제거(108지점) (for문 사용)

Code
## 풍향 각도와 풍향명 대응 데이터 생성
x=c(0,20,50,70,90,110,140,160,180,200,230,250,270,290,320,340,360)
y=c("북","북북동","북동","동북동","동","동남동","남동","남남동","남","남남서", "남서","서남서","서","서북서","북서","북북서","북")
name <- tibble(xname=x,yname=y) #방위명 표로 제작 
name 

climate_2018에 풍향명 추가

Code
climate_2018 <-mutate(climate_2018, wind_name=풍향) #wind_name 열 추가 
head(climate_2018)
Code
## for (i in seq_along(name$xname)) {
##  for(j in seq_along(name$xname)){ if(name$xname[j]==climate_2018$wind_name[i]){
##    climate_2018$wind_name[i] <- name$yname[j]
##  }
##    print(j)}
##  print("*") 
## } ### 17행까지만 제대로 시행 되는지 실험함. 
length(climate_2018$wind_name) #8760
[1] 8760
Code
length(name$xname) #17
[1] 17
Code
sum(is.na(climate_2018)) ##24개 있음. 
[1] 24
Code
anyNA(climate_2018) ##결측 여부 판단 
[1] TRUE
Code
climate_2018 <-na.omit(climate_2018) ###결측값 제거 
for (i in seq_along(climate_2018$wind_name)) {
  for(j in seq_along(name$xname)){ if(name$xname[j]==climate_2018$wind_name[i]){
    climate_2018$wind_name[i] <- name$yname[j]
  }
    }
     } ### 풍향 추가함 
sum(is.na(climate_2018)) #모든 값의 na여부 출력 
[1] 0
Code
climate_2018 <-  select(climate_2018,일시, 기온, 풍속, 풍향, 습도,wind_name)#측정 위치(지점) 제거 
#View(climate_2018)
head(climate_2018)

4. air_location 파일 정리, 측정소 이름 매치표 (place_name) 제작, air_hour_18n에 행정구역명 부여

Code
head(air_location)
Code
air_location_col_name <-c("측정소코드","측정소이름","측정소주소","표시순서","공인코드" )##열이름 띄어쓰기 없엠 
colnames(air_location) <- air_location_col_name 
air_location <-filter(air_location, air_location$측정소코드<=125) ##구별 위치만 선택
air_location$측정소코드 <- factor(air_location$측정소코드) #팩터형 변환
place_name <-tibble(x=air_location$측정소코드,y=air_location$측정소이름) #측정소 이름 매치표
str(place_name)
tibble [25 × 2] (S3: tbl_df/tbl/data.frame)
 $ x: Factor w/ 25 levels "101","102","103",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ y: chr [1:25] "종로구" "중구" "용산구" "은평구" ...
Code
air_hour_18n <-mutate(air_hour_18n, place_name1=place)

변수를 char형으로 바꾸어 매치표와 비교하고, place 번호에 맞는 행정구역 (구) 이름을 부여함. (실행 오래 걸림)

Code
air_hour_18n$place_name1 <-as.character(air_hour_18n$place_name1) 
place_name$x <-as.character(place_name$x)  # chr로 비교
for (i in seq_along(air_hour_18n$place_name1)) {
  for(j in seq_along(place_name$x)){ if(place_name$x[j]==air_hour_18n$place_name1[i]){
    air_hour_18n$place_name1[i] <- place_name$y[j]
  }
  }
}
place_name$x <-as.factor(place_name$x)
tail(air_hour_18n) # 적용 확인

5. air_hour_18n의 측정시간에 월, 일, 시간열 추가 (lubridate 사용)

Code
library(lubridate)
Loading required package: timechange

Attaching package: 'lubridate'
The following objects are masked from 'package:base':

    date, intersect, setdiff, union
Code
air_hour_18n <-mutate(air_hour_18n, month=month(time), 
              day=day(time), h_time=hour(time)) 
#View(air_hour_18n)
sum(is.na(air_hour_18n)) #4850, 110 line에서 확인했는데도 나옴.
[1] 0
Code
nrow(air_hour_18n) #214635 vs.###209785 row 
[1] 209785
Code
colSums(is.na(air_hour_18n)) # 열별로 결측 총합 계산, pm10, pm2.5에 결측있음.
       time       place        pm10       pm2.5 place_name1       month 
          0           0           0           0           0           0 
        day      h_time 
          0           0 
Code
which(is.na(air_hour_18n$pm10)) #결측 위치 확인
integer(0)
Code
air_hour_18n[19930,] #값 내용 확인, pm10과 pm2.5중 한개만 있는 값이 존재 
Code
air_hour_18n <-na.omit(air_hour_18n)
sum(is.na(air_hour_18n))
[1] 0

6. (시각화 병행) air_hour_18n에서 시간 세분화 값을 뺀 데이터 air_hour_18_global 생성 (단순화)

Code
air_hour_18_global<-select(air_hour_18n,time,pm10,pm2.5,place_name1)
air_hour_18_global$place_name1 <-as.factor(air_hour_18_global$place_name1)
str(air_hour_18_global)
tibble [209,785 × 4] (S3: tbl_df/tbl/data.frame)
 $ time       : POSIXct[1:209785], format: "2018-01-01 00:00:00" "2018-01-01 01:00:00" ...
 $ pm10       : num [1:209785] 29 27 30 28 28 32 29 29 31 26 ...
 $ pm2.5      : num [1:209785] 17 13 13 14 15 15 16 16 16 11 ...
 $ place_name1: Factor w/ 25 levels "강남구","강동구",..: 23 23 23 23 23 23 23 23 23 23 ...
 - attr(*, "na.action")= 'omit' Named int [1:4850] 2020 2334 2680 2681 2682 2686 2688 4285 4349 4380 ...
  ..- attr(*, "names")= chr [1:4850] "2020" "2334" "2680" "2681" ...
Code
head(air_hour_18_global)
Code
tail(air_hour_18_global)

7. air_hour_18n의 pm10 최대인 낮 14시 값만 추출하여 단순화 --> air_hour_18n_14h 생성

Code
summary(air_hour_18n)
      time                            place             pm10       
 Min.   :2018-01-01 00:00:00.00   115    :  8700   Min.   :  3.00  
 1st Qu.:2018-04-03 00:00:00.00   112    :  8691   1st Qu.: 20.00  
 Median :2018-07-02 20:00:00.00   120    :  8674   Median : 34.00  
 Mean   :2018-07-02 21:36:57.61   118    :  8650   Mean   : 39.73  
 3rd Qu.:2018-10-01 20:00:00.00   102    :  8649   3rd Qu.: 51.00  
 Max.   :2018-12-31 23:00:00.00   123    :  8647   Max.   :470.00  
                                  (Other):157774                   
     pm2.5        place_name1            month             day       
 Min.   :  1.00   Length:209785      Min.   : 1.000   Min.   : 1.00  
 1st Qu.: 10.00   Class :character   1st Qu.: 4.000   1st Qu.: 8.00  
 Median : 18.00   Mode  :character   Median : 7.000   Median :16.00  
 Mean   : 22.76                      Mean   : 6.538   Mean   :15.76  
 3rd Qu.: 30.00                      3rd Qu.:10.000   3rd Qu.:23.00  
 Max.   :204.00                      Max.   :12.000   Max.   :31.00  
                                                                     
     h_time     
 Min.   : 0.00  
 1st Qu.: 5.00  
 Median :11.00  
 Mean   :11.45  
 3rd Qu.:17.00  
 Max.   :23.00  
                
Code
max(air_hour_18n$pm10) ##미세먼지가 가장 많은 값?470
[1] 470
Code
which(air_hour_18n$pm10==470.00) ##미세먼지가 가장 많은 값의 행?178569
[1] 178569
Code
air_hour_18n[178569,]
Code
air_hour_18n_14h <-filter(air_hour_18n,h_time==14)
head(air_hour_18n_14h)
Code
tail(air_hour_18n_14h)
Code
summary(air_hour_18n_14h)##대표값 추출 필요, 초미세먼지 최대값이 안나옴 
      time                            place           pm10       
 Min.   :2018-01-01 14:00:00.00   115    : 361   Min.   :  3.00  
 1st Qu.:2018-04-03 14:00:00.00   112    : 357   1st Qu.: 22.00  
 Median :2018-07-03 14:00:00.00   118    : 356   Median : 36.00  
 Mean   :2018-07-03 08:54:45.21   101    : 354   Mean   : 41.87  
 3rd Qu.:2018-10-02 14:00:00.00   102    : 354   3rd Qu.: 53.00  
 Max.   :2018-12-31 14:00:00.00   116    : 353   Max.   :470.00  
                                  (Other):6465                   
     pm2.5        place_name1            month            day       
 Min.   :  1.00   Length:8600        Min.   : 1.00   Min.   : 1.00  
 1st Qu.: 10.00   Class :character   1st Qu.: 4.00   1st Qu.: 8.00  
 Median : 18.00   Mode  :character   Median : 7.00   Median :16.00  
 Mean   : 22.62                      Mean   : 6.55   Mean   :15.78  
 3rd Qu.: 30.00                      3rd Qu.:10.00   3rd Qu.:23.00  
 Max.   :138.00                      Max.   :12.00   Max.   :31.00  
                                                                    
     h_time  
 Min.   :14  
 1st Qu.:14  
 Median :14  
 Mean   :14  
 3rd Qu.:14  
 Max.   :14  
             
Code
max(air_hour_18n$pm2.5) ##초미세먼지 최대값204.00
[1] 204
Code
which(air_hour_18n$pm2.5==204.00) #134934
[1] 134934
Code
air_hour_18n[134934,] #초미세먼지 최대값 1월 20일 저녁 20시, 하루 그래프 필요 
Code
air_hour_18n[178568,] #357
Code
air_hour_18n[178567,] #228, 1시간에 100이상 차이남, 시간별 예보 필요?  

8. 10년간 추이 조사 위한 작업, 최대값 확인

Code
head(air_hour_10y)
Code
tail(air_hour_10y) #2018년 12월 31일까지  
Code
str(air_hour_10y)
spc_tbl_ [2,150,195 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ time : POSIXct[1:2150195], format: "2009-01-01 00:00:00" "2009-01-01 01:00:00" ...
 $ place: num [1:2150195] 101 101 101 101 101 101 101 101 101 101 ...
 $ pm10 : num [1:2150195] 38 44 29 31 34 38 33 42 48 32 ...
 $ pm2.5: num [1:2150195] 8 10 24 17 15 8 26 18 17 13 ...
 - attr(*, "spec")=
  .. cols(
  ..   X1 = col_datetime(format = ""),
  ..   X2 = col_double(),
  ..   X3 = col_double(),
  ..   X4 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
Code
air_hour_10y$place <-as.factor(air_hour_10y$place)
summary(air_hour_10y) #max 10pm:1354, max 2.5pm:250
      time                            place              pm10       
 Min.   :2009-01-01 00:00:00.00   122    :  86871   Min.   :   1.0  
 1st Qu.:2011-07-12 18:30:00.00   121    :  86749   1st Qu.:  25.0  
 Median :2014-01-03 13:00:00.00   107    :  86693   Median :  39.0  
 Mean   :2014-01-03 18:35:19.03   108    :  86539   Mean   :  45.8  
 3rd Qu.:2016-06-30 02:00:00.00   103    :  86528   3rd Qu.:  58.0  
 Max.   :2018-12-31 23:00:00.00   102    :  86417   Max.   :1354.0  
                                  (Other):1630398                   
     pm2.5       
 Min.   :  0.00  
 1st Qu.: 13.00  
 Median : 21.00  
 Mean   : 24.28  
 3rd Qu.: 31.00  
 Max.   :250.00  
                 

9. 18년 1-5월 데이터 필터링, pm10값이 큰 4월 6일 데이터 확인

Code
air_hour_18spring <-filter(air_hour_18n, month(time)<=5) 
tail(air_hour_18spring)
Code
air_hour_April6 <-filter(air_hour_18n, ((month(time)==4)&(day(time)==6))) #4월 6일 데이터
tail(air_hour_April6)
Code
summary(air_hour_April6) #pm10이 3~470에 분포 
      time                            place          pm10           pm2.5      
 Min.   :2018-04-06 00:00:00.00   101    : 24   Min.   :  3.0   Min.   : 1.00  
 1st Qu.:2018-04-06 06:00:00.00   102    : 24   1st Qu.:  9.0   1st Qu.: 6.00  
 Median :2018-04-06 12:00:00.00   104    : 24   Median : 91.0   Median :26.00  
 Mean   :2018-04-06 11:44:36.26   108    : 24   Mean   :121.3   Mean   :27.01  
 3rd Qu.:2018-04-06 18:00:00.00   109    : 24   3rd Qu.:215.0   3rd Qu.:44.00  
 Max.   :2018-04-06 23:00:00.00   110    : 24   Max.   :470.0   Max.   :88.00  
                                  (Other):425                                  
 place_name1            month        day        h_time     
 Length:569         Min.   :4   Min.   :6   Min.   : 0.00  
 Class :character   1st Qu.:4   1st Qu.:6   1st Qu.: 6.00  
 Mode  :character   Median :4   Median :6   Median :12.00  
                    Mean   :4   Mean   :6   Mean   :11.74  
                    3rd Qu.:4   3rd Qu.:6   3rd Qu.:18.00  
                    Max.   :4   Max.   :6   Max.   :23.00  
                                                           

10. 108번 관측소 날씨 데이터로 기후와 미세먼지 상관 관계 조사, mise_climate.Rmd와 연계, dustfeel.com 참조 (하루 4번: 5,11,5,11시 업데이트)

Code
air_hour_18_108 <- filter(air_hour_18n, place==108) #광진구, 날씨 데이터 있는곳 
tail(air_hour_18_108)
Code
str(air_hour_18_108) #8147행 
tibble [8,147 × 8] (S3: tbl_df/tbl/data.frame)
 $ time       : POSIXct[1:8147], format: "2018-01-01 00:00:00" "2018-01-01 01:00:00" ...
 $ place      : Factor w/ 25 levels "101","102","103",..: 8 8 8 8 8 8 8 8 8 8 ...
 $ pm10       : num [1:8147] 33 30 30 30 33 32 35 34 37 30 ...
 $ pm2.5      : num [1:8147] 16 14 15 15 16 17 19 21 25 20 ...
 $ place_name1: chr [1:8147] "광진구" "광진구" "광진구" "광진구" ...
 $ month      : num [1:8147] 1 1 1 1 1 1 1 1 1 1 ...
 $ day        : int [1:8147] 1 1 1 1 1 1 1 1 1 1 ...
 $ h_time     : int [1:8147] 0 1 2 3 4 5 6 7 8 9 ...
 - attr(*, "na.action")= 'omit' Named int [1:4850] 2020 2334 2680 2681 2682 2686 2688 4285 4349 4380 ...
  ..- attr(*, "names")= chr [1:4850] "2020" "2334" "2680" "2681" ...
Code
sum(is.na(air_hour_18_108)) #0
[1] 0
Code
sum(is.na(climate_2018)) #0
[1] 0
Code
str(climate_2018) #8740행 
tibble [8,740 × 6] (S3: tbl_df/tbl/data.frame)
 $ 일시     : POSIXct[1:8740], format: "2018-01-01 00:00:00" "2018-01-01 01:00:00" ...
 $ 기온     : num [1:8740] -3.2 -3.3 -3.7 -4 -4.2 -4.4 -4.5 -4.7 -5 -4.3 ...
 $ 풍속     : num [1:8740] 0.5 0.7 0.9 1 1.1 0.8 1.1 1.1 1 0.7 ...
 $ 풍향     : num [1:8740] 110 360 270 290 290 290 320 290 290 290 ...
 $ 습도     : num [1:8740] 40 41 42 44 53 54 51 56 55 39 ...
 $ wind_name: chr [1:8740] "동남동" "북" "서" "서북서" ...
 - attr(*, "na.action")= 'omit' Named int [1:20] 3320 3363 3364 3365 3366 3367 3368 3388 3389 3390 ...
  ..- attr(*, "names")= chr [1:20] "3320" "3363" "3364" "3365" ...

날씨데이터를 열이름 영문으로 변환 후, time을 기준으로 air_hour_18_108과 병합 (교재 9.2.2 left_join 사용)

Code
y <-c("time","temp","velocity","direction","humidity", "wind_name")
colnames(climate_2018) <-y
climate_18all <-climate_2018 %>%  left_join(air_hour_18_108, by="time") ##left_join
#View(climate_18all)
tail(climate_18all)
Code
sum(is.na(climate_18all)) #4305
[1] 4305
Code
climate_18all <- na.omit(climate_18all) #--->0
head(climate_18all) ##붙이기 성공!!!
Code
climate_18all <-select(climate_18all, time,temp,velocity,direction,humidity,wind_name,pm10,pm2.5,month,day,h_time)

11. 미세 먼지가 나쁨, 매우 나쁨 이상 값만 필터하여 지역별 비교

Code
library(dplyr)
pm10_bad <- filter(air_hour_18n, pm10 >=80)
head(pm10_bad)
Code
pm10_verybad <-filter(pm10_bad, pm10 >=150) 
pm2.5_bad <- filter(air_hour_18n, pm2.5 >=35)
pm2.5_verybad <- filter(air_hour_18n, pm2.5 >=75)
head(pm2.5_verybad)