R로 데이터 다루기

R에서 dplyr을 이용해 데이터를 추출, 가공하는 방법을 알아봅니다


수강중

11. 데이터 요약하기(group_by, summarise)

데이터를 요약하는 기능으로, R의 group by는 Excel의 pivot과 기능이 유사하다.

sales <- read.csv('sales.csv', stringsAsFactors = F,
                     fileEncoding = 'UTF-8')
colnames(sales) <- c('city', 'district', 'gender', 'sales.nm', 'sales.cd', 'ymd', 'sales.num')

library(dplyr)

판매건수 데이터로 실습

group by

group_by를 이용해 district 지역별로 그룹핑을 한다.

sales %>%
    group_by(district)
       city       district gender sales.nm sales.cd ymd      sales.num
1      서울특별시 강남구   남     스탑버스 12AA02   20140101 103      
2      서울특별시 강남구   여     키즈랜드 100101   20140101 309      
3      서울특별시 강남구   여     키즈랜드 100101   20140101 365      
4      서울특별시 강남구   남     스탑버스 12AA02   20140101 421      

summarise

summarise는 데이터를 요약해주는 함수이다.

sum

sales.numsumsummarise에 넘겨주면 구별로 판매건수 를 알 수 있다.

sales %>%
    group_by(district) %>%
    summarise(sum.sales.num = sum(sales.num))
   district sum.sales.num
1  강남구   2632978      
2  강동구   2623093      
3  강북구   2635469      
4  강서구   2637328      

mean

sum 대신에 mean을 사용하여 구별로 평균 판매 건수를 알 수 있다.

sales %>%
    group_by(district) %>%
    summarise(mean.sales.num = mean(sales.num))
   district mean.sales.num
1  강남구   250.7121      
2  강동구   248.9412      
3  강북구   250.7344      
4  강서구   249.9126      

group by (점포)

group_by를 이용해 sales.nm 점포별로 그룹핑을 한다. 결과로 점포별 판매건수 평균이 나온다.

sales %>%
    group_by(sales.nm) %>%
    summarise(mean.sales.num = mean(sales.num))
  sales.nm mean.sales.num
1 @        252.0024      
2 레스탑   250.4554      
3 베타문구 251.0429      
4 스탑버스 248.9897      
5 원조백반 249.9734      
6 원조한식 251.3319      
7 전주비빔 251.0797      
8 카페베타 251.1323      
9 키즈랜드 249.8582      

결측치, 특정값 처리

filter

최종 결과물에서 filter 처리

!= @ 를 사용해서 @가 아닌 것들을 선택 필터링 할 수 있다.

sales %>%
    group_by(sales.nm) %>%
    summarise(mean.sales.num = mean(sales.num)) %>%
    filter(sales.nm != '@')
  sales.nm mean.sales.num
1 레스탑   250.4554      
2 베타문구 251.0429      
3 스탑버스 248.9897      
4 원조백반 249.9734      
5 원조한식 251.3319      
6 전주비빔 251.0797      
7 카페베타 251.1323      
8 키즈랜드 249.8582      

결과물 이전에 filter 처리

속도면에서는 결과를 출력한 뒤에 @를 빼는 것보다 먼저 @를 미리 빼놓고 다음에 계산하는 것이 훨씬 좋다. 사실, 데이터가 크지 않으면 큰 차이가 없다.

sales %>%
    filter(sales.nm != '@') %>%
    group_by(sales.nm) %>%
    summarise(mean.sales.num = mean(sales.num))
  sales.nm mean.sales.num
1 레스탑   250.4554      
2 베타문구 251.0429      
3 스탑버스 248.9897      
4 원조백반 249.9734      
5 원조한식 251.3319      
6 전주비빔 251.0797      
7 카페베타 251.1323      
8 키즈랜드 249.8582      

group by (성별)

group_by를 이용해 gender (성별)로 그룹핑을 한다. 결과로 성별별 판매건수 평균가 나온다.

sales %>%
    group_by(gender) %>%
    summarise(mean.sales.num = mean(sales.num))
  gender mean.sales.num
1 NA     251.3390      
2 남     250.6194      
3 여     250.4969      

NA

is.naNA는 R에서 특별하게 missing을 다루는 특정 값이다. NA가 들어가 있는 데이터를 필터링하기 위해 filter(gender != NA) 하면 잘 되지 않는데, 이유는 R에서 NA를 특별대우를 해주기 때문이다.

is.na

NA의 경우에만 is.na라는 함수가 별도로 존재한다. is.na를 이용해 NA 값만 골라낸다. NA가 아닌 것만 고르려면 앞에 !를 붙여주면 된다.

!is.na을 이용해 성별이 NA인 것은 제외한다.

sales %>%
    filter(!is.na(gender)) %>%
    group_by(gender) %>%
    summarise(mean.sales.num = mean(sales.num))
  gender mean.sales.num
1 남     250.6194      
2 여     250.4969      

기후 데이터로 실습

기후 데이터를 불러온다.

climates <- read.csv('seoul_climate.csv', stringsAsFactors = F,
                     fileEncoding = 'UTF-8')

변수 이름 바꾸기

변수이름을 영어로 바꾼다.

colnames(climates) <- c('city', 'district', 'ym', 'lon', 'lat', 'rainfall')

group by(구)

group_by를 이용해 district (구)별로 강수량의 을 구한다.

climates %>%
    group_by(district) %>%
    summarise(sum.rainfall = sum(rainfall))
   district sum.rainfall
1  강남구     NA        
2  강동구     NA        
3  강북구   2204        
4  강서구     NA        

NA 관련 옵션

na.rm

R에서 sum이나 mean을 할 때 miising 값 NA가 들어가 있으면 결과로 NA가 출력한다. na.rm = T로 하여 NA 값을 제거한다.

climates %>%
    group_by(district) %>%
    summarise(sum.rainfall = sum(rainfall, na.rm = T))
   district sum.rainfall
1  강남구   1554        
2  강동구   1678        
3  강북구   2204        
4  강서구   2124        

group_by(연월, 구)

group_by를 이용해 ym, district (연월 & 구)별로 강수량 평균 구한다. chain 뒤에 print(n=100)을 이용해 100개를 출력한다.

climates %>%
    group_by(ym, district) %>%
    summarise(sum.rainfall = sum(rainfall, na.rm = T))
    ym     district sum.rainfall
1   201401 강남구     0         
2   201401 강동구     0         
3   201401 강북구     0         
4   201401 강서구   192         

chain 뒤에 print(n=100)을 이용해 100개를 출력한다.

climates %>%
    group_by(ym, district) %>%
    summarise(sum.rainfall = sum(rainfall, na.rm = T)) %>%
    print(n = 100)
# A tibble: 600 x 3
# Groups:   ym [24]
        ym district sum.rainfall
     <int> <chr>           <int>
  1 201401 강남구              0