[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.grade을 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)) %>%
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