R로 데이터 다루기

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


수강중

15. dplyr 함수들을 조합한 실전 데이터 다루기 2 - 2

6번 문제

구별 판매건수의 합을 남 녀 별로 비교해주세요.

group_by, summarise

구별이니 group_by에 구가 들어가고, 남녀별로 라고 했으니깐 뒤에 gender가 들어간다. 그리고 summarise, sum를 해주면 된다.

sales %>%
    group_by(district, gender) %>%
    summarise(sum.sales.num = sum(sales.num, na.rm = T))
    district gender sum.sales.num
1   강남구   NA      261586      
2   강남구   남     1182813      
3   강남구   여     1188579      
4   강동구   NA      267583      

NA 값 처리

filter(!is.na(gender))NA가 아닌 것을 추려낸다.

sales %>%
    filter(!is.na(gender)) %>%
    group_by(district, gender) %>%
    summarise(sum.sales.num = sum(sales.num, na.rm = T))
   district gender sum.sales.num
1  강남구   남     1182813      
2  강남구   여     1188579      
3  강동구   남     1173535      
4  강동구   여     1181975      

7번 문제

강남구에서 월별 판매건수의 합을 남 녀 별로 비교해주세요.

filter

filter를 해서 강남구를 선택한다.

sales %>%
    filter(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      

mutate

데이터가 일별 데이터이기 때문에 m(월) 변수를 만들어준다. mutate, substr을 사용해 ymd를 잘라 만든다.

sales %>%
    filter(district == '강남구') %>%
    mutate(m = substr(ymd, 5, 6))
      city       district gender sales.nm sales.cd ymd      sales.num m  
1     서울특별시 강남구   남     스탑버스 12AA02   20140101 103       01 
2     서울특별시 강남구   여     키즈랜드 100101   20140101 309       01 
3     서울특별시 강남구   여     키즈랜드 100101   20140101 365       01 
4     서울특별시 강남구   남     스탑버스 12AA02   20140101 421       01 

강남구 조건에 !is.na를 하면 NA가 아닌 데이터를 추출된다.

sales %>%
    filter(district == '강남구' & !is.na(gender)) %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(m, gender) %>%
    summarise(sum.sales.num = sum(sales.num, na.rm = T))
   m  gender sum.sales.num
1  01 남     124241       
2  01 여     119220       
3  02 남      82757       
4  02 여      80253       
5  03 남      95705       
6  03 여      98662       
7  04 남      94527       
8  04 여      92161       
9  05 남     108618       
10 05 여     103917       
11 06 남      95979       
12 06 여     102209       
13 07 남      95862       
14 07 여      96153       
15 08 남      96305       
16 08 여     105486       
17 09 남      92653       
18 09 여      99071       
19 10 남      96847       
20 10 여      96261       
21 11 남     102357       
22 11 여      97655       
23 12 남      96962       
24 12 여      97531       

8번 문제

관악구와 강남구에서 구별로 일별 판매건수가 가장 큰 점포와 해당 날짜를 추출하세요.

filter

district %in%을 사용해 관악구와 강남구의 데이터만 선택한다.

sales %>%
    filter(district %in% c('관악구', '강남구'))
      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      

group_by, arrange(desc), slice

group_by로 구별로 그룹핑을 한후

sales %>%
    filter(district %in% c('관악구', '강남구')) %>%
    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      

arrange(desc)으로 sales.num(판매건수)를 내림차순 정렬한다. 그리고 첫번째 데이터를 슬라이싱한다.

sales %>%
    filter(district %in% c('관악구', '강남구')) %>%
    group_by(district) %>%
    arrange(desc(sales.num)) %>%
    slice(1)
  city       district gender sales.nm sales.cd ymd      sales.num
1 서울특별시 강남구   여     원조한식 100201   20140116 500      
2 서울특별시 관악구   여     키즈랜드 100101   20140520 500      

문제 해결 1

성별에 관계없이 일별 판매건수 합을 구해야 한다.

group_by에 구별, 일별, 점포명을 넘겨줘야한다. 지역의 city가 겹칠 수 있으니 city도 넣어줘야한다.

sales %>%
    filter(district %in% c('관악구', '강남구')) %>%
    group_by(city, district, sales.nm, ymd) %>%
    summarise(sum.sales.num = sum(sales.num, na.rm = T)) %>%
    group_by(district) %>%
    arrange(desc(sum.sales.num)) %>%
    slice(1)
  city       district sales.nm ymd      sum.sales.num
1 서울특별시 강남구   @        20141107 7140         
2 서울특별시 관악구   스탑버스 20141111 7264         

문제 해결 2

동률에 대한 데이터

이 부분을 mutaterank를 이용하여 구별로 순위를 매긴다. 높은 것에서 낮은 순으로 순위를 매기고 동률이 날 경우 최소값을 넣어주도록 한다.

sales %>%
    filter(district %in% c('관악구', '강남구')) %>%
    group_by(city, district, sales.nm, ymd) %>%
    summarise(sum.sales.num = sum(sales.num, na.rm = T)) %>%
    group_by(district) %>%
    mutate(rank = rank(-sum.sales.num, ties.method = 'min'))
     city       district sales.nm ymd      sum.sales.num rank
1    서울특별시 강남구   @        20140101 3561          458 
2    서울특별시 강남구   @        20140106 4266          258 
3    서울특별시 강남구   @        20140111 2415          636 
4    서울특별시 강남구   @        20140116 4837          106 

filter를 하여 순위가 1인 것만 뽑도록 한다. 그리고 print를 한다.

sales %>%
    filter(district %in% c('관악구', '강남구')) %>%
    group_by(city, district, sales.nm, ymd) %>%
    summarise(sum.sales.num = sum(sales.num, na.rm = T)) %>%
    group_by(district) %>%
    mutate(rank = rank(-sum.sales.num, ties.method = 'min')) %>%
    filter(rank == 1) %>%
    print(n = 100)
# A tibble: 2 x 6
# Groups:   district [2]
  city       district sales.nm      ymd sum.sales.num  rank
  <chr>      <chr>    <chr>       <int>         <int> <int>
1 서울특별시 강남구   @        20141107          7140     1

9-1번 문제

일별 평균 판매건수를 성별로 비교해보세요.

group_by에 성별을 넣고 summarise를 한다.

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

9-2번 문제

일별 판매건수를 구, 연월일, 성별을 고려하여 최댓값을 만들고, 즉, 점포명을 무시하고 이 최댓값의 평균을 성별로 비교해보세요.

group_by를 사용하여 구별, 연월일별, 성별 변수를 넘겨주고 summarisemax함수를 적용한다.

sales %>%
    group_by(district, ymd, gender) %>%
    summarise(max.sales.num = max(sales.num, na.rm = T))
     district ymd      gender max.sales.num
1    강남구   20140101 NA     463          
2    강남구   20140101 남     496          
3    강남구   20140101 여     496          
4    강남구   20140106 NA     464          

그리고 다시 성별로 비교하는 것이기 때문에 성별로 묶어준다. 그리고 다시 summarise로 하여 max 값의 평균을 구한다.

sales %>%
    group_by(district, ymd, gender) %>%
    summarise(max.sales.num = max(sales.num, na.rm = T)) %>%
    group_by(gender) %>%
    summarise(mean.sales.num = mean(max.sales.num, na.rm = T))
  gender mean.sales.num
1 NA     465.0252      
2 남     493.2603      
3 여     493.2164      

10번 문제

판매건수를 기준으로 2014년 중 지역별 & 점포별로 성별 등은 무시하고 평균값을 구해 내림차순 정렬하되, 지역별 & 점포별로 TOP 2개만 뽑아주세요. 단, @ 점포는 제외하시오.

먼저 @로 되어있는 점포를 제외하자. filter@는 제외하고 mutate로 년 변수를 만들어준다.

sales %>% filter(sales.nm != '@') %>%
    mutate(y = substr(ymd, 1, 4)) %>%
    filter(y == '2014')
       city       district gender sales.nm sales.cd ymd      sales.num y   
1      서울특별시 강남구   남     스탑버스 12AA02   20140101 103       2014
2      서울특별시 강남구   여     키즈랜드 100101   20140101 309       2014
3      서울특별시 강남구   여     키즈랜드 100101   20140101 365       2014
4      서울특별시 강남구   남     스탑버스 12AA02   20140101 421       2014

그 다음 filter를 이용해서 2014년도만 뽑아낸다. 그리고 group_by로 구별, 점포별를 넘겨주고 summarise로 평균을 구한다.

sales %>% filter(sales.nm != '@') %>%
    mutate(y = substr(ymd, 1, 4)) %>%
    filter(y == '2014') %>%
    group_by(district, sales.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm =T))
    district sales.nm mean.sales.num
1   강남구   레스탑   245.9457      
2   강남구   베타문구 245.6988      
3   강남구   스탑버스 248.3998      
4   강남구   원조백반 256.6305      

그리고 arrangedesc를 사용하여 내림차순으로 정렬하고 slice로 첫 번째와 두 번째 데이터를 뽑아낸다.

sales %>% filter(sales.nm != '@') %>%
    mutate(y = substr(ymd, 1, 4)) %>%
    filter(y == '2014') %>%
    group_by(district, sales.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm =T)) %>%
    arrange(desc(mean.sales.num)) %>%
    slice(1:2)
   district sales.nm mean.sales.num
1  강남구   원조한식 260.7767      
2  강남구   원조백반 256.6305      
3  강동구   전주비빔 256.2129      
4  강동구   스탑버스 254.4223      

2014년이 데이터에 잘 들어가 있는지 확인한다.

sales %>% filter(sales.nm != '@') %>%
    mutate(y = substr(ymd, 1, 4)) %>%
    filter(y == '2014') %>%
    group_by(y, district, sales.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm =T)) %>%
    arrange(desc(mean.sales.num)) %>%
    slice(1:2) %>%
    print(n = 100)
# A tibble: 50 x 4
# Groups:   y, district [25]
   y     district sales.nm mean.sales.num
   <chr> <chr>    <chr>             <dbl>
 1 2014  강남구   원조한식           261.