logo

[dplyr] dplyr 함수들을 조합한 실전 데이터 다루기 3

 

데이터 불러오기

변수명도 변경하기 데이터를 불러오고 변수명을 변경하는 법은 앞의 강의들을 참조해주기바란다. 대신 코드는 올린다. 판매 데이터, 업종 코드 데이터, 강수량이 들어있는 기후 데이터를 다 불러오고 변수명을 영문으로 변경하였다.

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

products <- read.csv("productcode.csv", stringsAsFactors = F,
                     fileEncoding = "UTF-8")
colnames(products) <- c('products.cd', 'products.nm')

climates <- read.csv('seoul_climate.csv', stringsAsFactors = F,
                     fileEncoding = 'UTF-8')
colnames(climates) <- c('city', 'district', 'ym', 'lat', 'lon', 'rainfall')

판매 데이터에 업종 데이터와 join

 

mutate

판매 데이터에 업종 데이터와 join 하기 위해 변수를 생성한다. 두 데이터를 합치려면 동일한 업종코드products.cd가 판매 데이터에 있으면 키로 두 데이터를 합칠 수 있다. 그런데 판매 데이터에는 업종코드가 없다. 그래서 mutate를 이용하여 products.cd를 생성하여 join을 해주자.

sales <- sales %>%
    mutate(products.cd = substr(sales.cd, 1, 4))
 

판매 데이터에 업종 데이터와 join

그 이후에 left join을 해 판매 데이터를 확인하면 업종 코드가 있는 것을 알 수 있다.

sales <- sales %>%
    mutate(products.cd = substr(sales.cd, 1, 4))
sales <- left_join(sales, products)
sales %>% head
Joining, by = "products.cd"

  city       district gender sales.nm sales.cd ymd      sales.num products.cd
1 서울특별시 강남구   남     스탑버스 12AA02   20140101 103       12AA
2 서울특별시 강남구   여     키즈랜드 100101   20140101 309       1001
3 서울특별시 강남구   여     키즈랜드 100101   20140101 365       1001
4 서울특별시 강남구   남     스탑버스 12AA02   20140101 421       12AA
5 서울특별시 강남구   여     스탑버스 12AA02   20140101 413       12AA
6 서울특별시 강남구   남     키즈랜드 100101   20140101 428       1001
  products.nm
1 카페
2 유아용품
3 유아용품
4 카페
5 카페
6 유아용품
 

mutate

판매 데이터에 기후 데이터와 join 하기 위해 변수를 생성한다. 마찬가지로 기후 데이터에 연월 이라는 변수를 추가해주자.

sales <- sales %>%
    mutate(ym = substr(ymd, 1, 6))
 

as.character

기후 데이터에서는 연월 변수가 숫자로 되어있어서 as.character로 변환하자.

climates$ym <- as.character(climates$ym)
 

판매 데이터에 기후 데이터와 join

sales <- sales %>%
    mutate(products.cd = substr(sales.cd, 1, 4))
sales <- left_join(sales, products)
sales %>% head

sales <- sales %>%
    mutate(ym = substr(ymd, 1, 6))
climates$ym <- as.character(climates$ym)
sales <- left_join(sales, climates)
sales %>% head
Joining, by = c("products.cd", "products.nm")

  city       district gender sales.nm sales.cd ymd      sales.num products.cd
1 서울특별시 강남구   남     스탑버스 12AA02   20140101 103       12AA
2 서울특별시 강남구   여     키즈랜드 100101   20140101 309       1001
3 서울특별시 강남구   여     키즈랜드 100101   20140101 365       1001
4 서울특별시 강남구   남     스탑버스 12AA02   20140101 421       12AA
5 서울특별시 강남구   여     스탑버스 12AA02   20140101 413       12AA
6 서울특별시 강남구   남     키즈랜드 100101   20140101 428       1001
  products.nm ym
1 카페        201401
2 유아용품    201401
3 유아용품    201401
4 카페        201401
5 카페        201401
6 유아용품    201401
Joining, by = c("city", "district", "ym")

  city       district gender sales.nm sales.cd ymd      sales.num products.cd
1 서울특별시 강남구   남     스탑버스 12AA02   20140101 103       12AA
2 서울특별시 강남구   여     키즈랜드 100101   20140101 309       1001
3 서울특별시 강남구   여     키즈랜드 100101   20140101 365       1001
4 서울특별시 강남구   남     스탑버스 12AA02   20140101 421       12AA
5 서울특별시 강남구   여     스탑버스 12AA02   20140101 413       12AA
6 서울특별시 강남구   남     키즈랜드 100101   20140101 428       1001
  products.nm ym     lat      lon     rainfall
1 카페        201401 37.49666 127.063 NA
2 유아용품    201401 37.49666 127.063 NA
3 유아용품    201401 37.49666 127.063 NA
4 카페        201401 37.49666 127.063 NA
5 카페        201401 37.49666 127.063 NA
6 유아용품    201401 37.49666 127.063 NA
 

1번 문제

업종별(products.nm) 평균 판매건수를 구하세요. 단, NA 업종은 제외하세요.

 

group_by, filter, summarise

group_by를 하고, NA를 제외하기 위해 filter를 한다. filter를 뒤에 하든 앞에 하든 상관없는데 보통 앞에 하는게 좋다. 그리고 summarise를 하여 평균 판매건수를 구한다.

sales %>%
    filter(!is.na(products.nm)) %>%
    group_by(products.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T))
  products.nm mean.sales.num
1 완구        250.7495
2 유아용품    249.8582
3 카페        250.0636
4 한식        250.7960
 

2번 문제

한식 업종의 월별 평균 판매건수를 구하고, 내림차순으로 정렬을 하세요.

 

filter

위와 다른 것은 월별로 구하는 것이 필요하고 한식업종만 구하면 된다.

sales %>%
    filter(products.nm == '한식')
      city       district gender sales.nm sales.cd ymd      sales.num
1     서울특별시 강남구   남     원조한식 100201   20140101 363
2     서울특별시 강남구   남     원조백반 100202   20140101 480
3     서울특별시 강남구   여     원조백반 100202   20140101  25
4     서울특별시 강남구   여     전주비빔 100203   20140101 415

...
 

mutate

그 다음에 월별이라 했는데 월 변수가 없기 때문에 mutate로 월 변수를 구한다.

sales %>%
    filter(products.nm == '한식') %>%
    mutate(m = substr(ymd, 5, 6))
      city       district gender sales.nm sales.cd ymd      sales.num
1     서울특별시 강남구   남     원조한식 100201   20140101 363
2     서울특별시 강남구   남     원조백반 100202   20140101 480
3     서울특별시 강남구   여     원조백반 100202   20140101  25
4     서울특별시 강남구   여     전주비빔 100203   20140101 415

...
 

group_by, summarise

월별 판매 건수이니 group_by가 들어가고 summarise 평균이 들어간다.

sales %>%
    filter(products.nm == '한식') %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(products.nm, m) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T))
   products.nm m  mean.sales.num
1  한식        01 253.7554
2  한식        02 252.7710
3  한식        03 250.3631
4  한식        04 249.7209
5  한식        05 251.9256
6  한식        06 250.1250
7  한식        07 249.2496
8  한식        08 249.2152
9  한식        09 253.0379
10 한식        10 246.7699
11 한식        11 252.1547
12 한식        12 250.6891
 

arrange

그 다음에 내림차순 정렬이니 desc를 쓴 arrange를 해주면 된다. 월별 평균 판매건수를 정렬해주면 된다.

sales %>%
    filter(products.nm == '한식') %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(products.nm, m) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T)) %>%
    arrange(desc(mean.sales.num))
   products.nm m  mean.sales.num
1  한식        01 253.7554
2  한식        09 253.0379
3  한식        02 252.7710
4  한식        11 252.1547
5  한식        05 251.9256
6  한식        12 250.6891
7  한식        03 250.3631
8  한식        06 250.1250
9  한식        04 249.7209
10 한식        07 249.2496
11 한식        08 249.2152
12 한식        10 246.7699
 

3번 문제

매출데이터에서 월별 & 구별 & 업종(products.nm)별 평균 판매 건수와 평균 강수량을 구하세요. 단, 평균 판매 건수와 평균 강수량이 NA인 것은 제외하세요.

판매 데이터에 월 변수가 없기 때문에 mutate을 사용해 월 변수를 만들고, group_by를 사용하여 월별 구별 업종별이 다 들어가기 때문에 넣어준다.

그리고 summarise를 하여 평균 판매건수, 평균 강수량을 구한다.

sales %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(m, district, products.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T),
              mean.rainfall = mean(rainfall, na.rm = T))
     m   district products.nm mean.sales.num mean.rainfall
1    01  강남구   NA          275.4787       NaN
2    01  강남구   완구        239.6862       NaN
3    01  강남구   유아용품    266.5385       NaN
4    01  강남구   카페        249.7489       NaN

...
 

NA 처리

코드 뒤에 filter를 하여 is.na로 평균 판매건수와 평균 강수량에서 NA값을 제외한다.

sales %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(m, district, products.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T),
              mean.rainfall = mean(rainfall, na.rm = T)) %>%
    filter(!is.na(mean.sales.num) & !is.na(mean.rainfall))
     m   district products.nm mean.sales.num mean.rainfall
1    01  강북구   NA          254.6341         0
2    01  강북구   완구        250.7737         0
3    01  강북구   유아용품    230.0101         0
4    01  강북구   카페        271.1531         0

...
 

4번 문제

3번의 결과에서 평균 강수량mean.rainfall을 250 이상은 '상', 50 ~ 250은 '중', 50미만은 '하'로 바꾸어 새로운 변수에 저장하세요.

 

mutate, ifelse

위의 코드를 붙여놓고 mutate로 새로운 변수를 만들어준다. 조건이 들어가기 때문에 ifelse를 사용한다. 250보다 크면 '상', 그게 아닐 때는 조건을 하나 더 줄 수 있다. 250보다 작은 경우에 한해서 50보다 크면 '중' 아니면 '하'로 한다.

sales %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(m, district, products.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T),
              mean.rainfall = mean(rainfall, na.rm = T)) %>%
    filter(!is.na(mean.sales.num) & !is.na(mean.rainfall)) %>%
    mutate(rainfall.grade = ifelse(mean.rainfall >= 250, '상',
                                   ifelse(mean.rainfall >= 50, '중', '하')))
     m   district products.nm mean.sales.num mean.rainfall rainfall.grade
1    01  강북구   NA          254.6341         0           하
2    01  강북구   완구        250.7737         0           하
3    01  강북구   유아용품    230.0101         0           하
4    01  강북구   카페        271.1531         0           하

...
 

5번 문제

4번 결과에서 평균 강수량 등급(rainfall.grade) 별 평균 판매건수(mean.sales.num)의 평균을 다시 구해보세요.

 

group_by, summarise

강수량 등급rainfall.gradegroup_by로 묶어주고 summarise로 평균 판매건수와 강수량을 구한다.

sales %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(m, district, products.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T),
              mean.rainfall = mean(rainfall, na.rm = T)) %>%
    filter(!is.na(mean.sales.num) & !is.na(mean.rainfall)) %>%
    mutate(rainfall.grade = ifelse(mean.rainfall >= 250, '상',
                                   ifelse(mean.rainfall >= 50, '중', '하'))) %>%
    group_by(rainfall.grade) %>%
    summarise(mean.mean.sales.num = mean(mean.sales.num, na.rm = T))
  rainfall.grade mean.mean.sales.num
1 상             248.6016
2 중             250.7814
3 하             250.9025
 

코드를 효과적으로 짜기

3번을 mean.sales변수에 저장하고 거기에 chain을 하여 뒷 단계를 할 수 있다.

mean.sales <- sales %>%
    mutate(m = substr(ymd, 5, 6)) %>%
    group_by(m, district, products.nm) %>%
    summarise(mean.sales.num = mean(sales.num, na.rm = T),
              mean.rainfall = mean(rainfall, na.rm = T)) %>%
    filter(!is.na(mean.sales.num) & !is.na(mean.rainfall))

변수를 만들고 다시한번 밑에서 작업을 해도 큰 무리가 없다.

mean.sales %>%
    mutate(rainfall.grade = ifelse(mean.rainfall >= 250, '상',
                                   ifelse(mean.rainfall >= 50, '중', '하'))) %>%
    group_by(rainfall.grade) %>%
    summarise(mean.mean.sales.num = mean(mean.sales.num, na.rm = T))
  rainfall.grade mean.mean.sales.num
1 상             248.6016
2 중             250.7814
3 하             250.9025
Previous
다른 데이터 합치기(join)