Subsetting Data

외부에서 불러 온 Data는 내가 원하지 않는 data도 다량 포함하고 있습니다.

행/열로 지정하기

Data 준비

서울시 일별 평균 대기오염도 정보페이지에서 [내려받기(CSV)]를 클릭하여 자료를 내려받습니다.

   1 df <- read.csv(file.choose(), fileEncoding = 'euc-kr')
   2 # file.choose()의 결과물을 read.csv()에 넣습니다.
   3 # fileEncoding 옵션은 macOS에서 필요합니다. Windows에서는 있어도 없어도 됩니다.
   4 
   5 str(df)
   6 head(df)

> str(df)
'data.frame':   18094 obs. of  8 variables:
 $ 측정일시           : int  20200922 20200922 20200922 20200922 20200922 20200922 20200922 20200922 20200922 20200922 ...
 $ 측정소명           : chr  "강남구" "강남대로" "강동구" "강변북로" ...
 $ 이산화질소농도.ppm.: num  0.016 0.03 0.015 0.011 0.011 0.017 NA 0.02 0.01 0.009 ...
 $ 오존농도.ppm.      : num  0.022 0.011 0.02 0.027 0.017 0.023 NA 0.021 0.034 0.018 ...
 $ 일산화탄소농도.ppm.: num  0.3 0.6 0.3 0.4 0.3 0.2 NA 0.4 0.4 0.4 ...
 $ 아황산가스.ppm.    : num  0.003 0.003 0.002 0.003 0.002 0.003 NA 0.002 0.003 0.002 ...
 $ 미세먼지.....      : int  13 14 14 9 17 13 NA 15 NA 12 ...
 $ 초미세먼지.....    : int  9 10 8 6 9 8 NA 7 3 4 ...

> head(df)
  측정일시 측정소명 이산화질소농도.ppm. 오존농도.ppm. 일산화탄소농도.ppm. 아황산가스.ppm.  미세먼지..... 초미세먼지.....
1 20200922   강남구             0.016         0.022              0.3           0.003           13               9
2 20200922 강남대로             0.030         0.011              0.6           0.003           14              10
3 20200922   강동구             0.015         0.020              0.3           0.002           14               8
4 20200922 강변북로             0.011         0.027              0.4           0.003            9               6
5 20200922   강북구             0.011         0.017              0.3           0.002           17               9
6 20200922   강서구             0.017         0.023              0.2           0.003           13               8

data.frame[행,열]

data.frame[행,열] 순서로 위치(index)를 지정하여 원하는 데이터를 지정할 수 있습니다.

다음은 어떤 결과가 나오겠는지 먼저 예상하고, 실행 해 보세요.

   1 df[3,2]
   2 df[c(3:8),2]
   3 df[c(3:8),c(1,2,4)]
   4 df[      ,c(1,2,4)]

TRUE/FALSE 조건으로 나누기

조건 연산자 사용

다음은 df에 저장된 data.frame에서 이름이 '측정소명'인 vector를 화면에 출력합니다.

   1 df$측정소명

> df$측정소명
 [1] "강남구"       "강남대로"     "강동구"       "강변북로"     "강북구"
 [6] "강서구"       "공항대로"     "관악구"       "관악산"       "광진구"
[11] "구로구"       "궁동"         "금천구"       "남산"         "노원구"
[16] "도봉구"       "도산대로"     "동대문구"     "동작구"       "동작대로"
[21] "마포구"       "마포아트센터" "북한산"       "서대문구"     "서울숲"
[26] "서초구"       "성동구"       "성북구"       "세곡"         "송파구"
[31] "시흥대로"     "신촌로"       "양천구"       "영등포구"     "영등포로"
[36] "올림픽공원"   "용산구"       "은평구"       "자연사박물관" "정릉로"
[41] "종로"         "종로구"       "중구"         "중랑구"       "천호대로"
[46] "청계천로"     "한강대로"     "행주"         "홍릉로"       "화랑로"
[51] "강남구"       "강남대로"     "강동구"       "강변북로"     "강북구"
[56] "강서구"       "공항대로"     "관악구"       "관악산"       "광진구"
[61] "구로구"       "궁동"         "금천구"       "남산"         "노원구"
[66] "도봉구"       "도산대로"     "동대문구"     "동작구"       "동작대로"
.......(중략).......
[951] "강남구"       "강남대로"     "강동구"       "강변북로"     "강북구"
[956] "강서구"       "공항대로"     "관악구"       "관악산"       "광진구"
[961] "구로구"       "궁동"         "금천구"       "남산"         "노원구"
[966] "도봉구"       "도산대로"     "동대문구"     "동작구"       "동작대로"
[971] "마포구"       "마포아트센터" "북한산"       "서대문구"     "서울숲"
[976] "서초구"       "성동구"       "성북구"       "세곡"         "송파구"
[981] "시흥대로"     "신촌로"       "양천구"       "영등포구"     "영등포로"
[986] "올림픽공원"   "용산구"       "은평구"       "자연사박물관" "정릉로"
[991] "종로"         "종로구"       "중구"         "중랑구"       "천호대로"
[996] "청계천로"     "한강대로"     "행주"         "홍릉로"       "화랑로"
[ reached getOption("max.print") -- omitted 17094 entries ]

비교 연산자

R에서 vector에 계산을 지시하면 element-wise 계산을 합니다.

비교 연산자는 계산 결과가 TRUE/FALSE 로 나옵니다.

다음은 df$측정소명 에 저장된 element가 관악구와 같은지 하나하나 비교하여 TRUE 혹은 FALSE를 출력합니다.

   1 df$측정소명 == '관악구'

[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[15] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[29] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[43] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[57] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
.......(중략).......
[953] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[967] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[981] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[995] FALSE FALSE FALSE FALSE FALSE FALSE
[ reached getOption("max.print") -- omitted 17094 entries ]

이 T/F 벡터를 행index로 지정하면 TRUE 값에 해당하는 행만 subset 됩니다.

   1 GA <- df[df$측정소명 == '관악구',  ]
   2 head(GA)

T/F vector로 지정하는 법과 index를 지정하는 법을 혼합해도 됩니다.

   1 # 측정소가 관악구인 row의 1,2,7번째 column 지정
   2 GA_dust <- df[df$측정소명 == '관악구', c(1,2,7)]
   3 head(GA_dust, 10)

%in% 연산자

A가 B에 포함되어 있는지가 궁금할 때는 A %in% B 이렇게 씁니다.

   1 df$측정소명 %in% c('관악구','강동구')

[1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[15] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[29] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[43] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
[57] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
.......(중략).......
[953]  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[967] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[981] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[995] FALSE FALSE FALSE FALSE FALSE FALSE
[ reached getOption("max.print") -- omitted 17094 entries ]

다음은 어떤 결과가 나올까요?

   1 # 측정소가 관악구인 row의 1,2,7번째 column 지정
   2 GAGD_dust <- df[df$측정소명 %in% c('관악구','강동구'), c(1,2,7)]
   3 head(GAGD_dust, 10)

grep( ) 사용

grep(찾을 패턴, 데이타) 이렇게 쓰면 데이타에 패턴이 보이면 TRUE, 아니면 FALSE 가 됩니다.

서울시 일별 평균 대기오염도 정보에서 2019년 11월의 데이타만 subset하고 싶을 때 %in% 를 사용한다면 이렇게 합니다.

   1 df[df$측정일시 %in% c(20191101, 20191102, 20191103, ...(모두 다 적어)... 20191130),   ]

grep( )을 사용하면 이렇게 합니다.

   1 df[ grep('201911', df$측정일시) ,   ] # 측정일시에 201911이 보이면 TRUE

정규식을 사용하면 더 확실하게 하면 이렇게 합니다.

   1 df[ grep('^201911', df$측정일시) ,   ] # 측정일시 처음이 201911이면 TRUE

2019년 11월의 미세먼지 컬럼만 따오고 싶으면 이렇게 합니다.

   1 df[ grep('^201911', df$측정일시) , '미세먼지.....'  ]
   2 # 주의: 특수문자 때문에 미세먼지 컬럼 이름이 '미세먼지.....' 이렇습니다.

데이타 전처리 마무리

Corona19 로 우리가 얻은 몇가지 안 되는 장점 중 하나는 깨끗한 공기입니다. 진짜 그런지 봐 봅시다.

   1 df <- read.csv(file.choose(), fileEncoding = 'euc-kr')
   2 
   3 # 측정소명을 보면 OO구와 OO대로 이렇게 섞여 있습니다.
   4 # 예를 들어 종로구와 종로가 따로 입력되어 있으면 종로구 공기질이 두번 들어가서 over-representing 될 수 있으므로
   5 # 측정소가 OO구인 데이타만 취하고 나머지는 버리겠습니다.
   6 # df 중 측정소명이 '구'로 끝나는 패턴만 따로 모아서 df 를 update 합니다.
   7 df <- df[ grep('구$', df$측정소명), ]
   8 
   9 dust19 <- data.frame(month = as.factor('2019.11'),
  10                      pm10 = df[ grep('^201911', df$측정일시) , '미세먼지.....'  ]
  11                      )
  12 head(dust19)

    month pm10
1 2019.11   51
2 2019.11   52
3 2019.11   45
4 2019.11   67
5 2019.11   46
6 2019.11   35

동일한 방법으로 dust20 data.frame을 만들고 dust19와 dust20을 위아래로 붙혀줍니다

   1 dust20 <- data.frame(month = as.factor('2020.05'),
   2                      pm10 = df[ grep('^202005', df$측정일시) , '미세먼지.....'  ]
   3                      )
   4 
   5 dust = rbind(dust19, dust20) # rbind( ): row 방향으로 붙힙니다.
   6 summary(dust)

컬럼을 (month, pm10) 대신 (pm10@2019, pm10@2020)으로 구성하는 것은 직관적이지만 더 귀찮은 오류의 가능성을 키웁니다.

   1 boxplot(pm10 ~ month, data=dust, col=c('brown2','deepskyblue'))
   2 
   3 # 참고로 r에서 사용 가능한 colors list를 보고 싶으면 다음을 실행하세요.
   4 colors()

pm10_boxplot.png

이 차이가 통계적으로 유의미한 차이인지 궁금하다면??


Class/Statistics/RBasic3 (2020-09-19 17:51:20에 gehoon가(이) 마지막으로 수정)