네이버 2차 코테 대비 데이터 전처리(R 이용)
🟢 네이버 2차 코테 대비 데이터 전처리(R 이용)
본 포스팅에 이용되는 데이터 처리 문제들은 Do it! 쉽게 배우는 R 데이터 분석(김영우 저)
에 근거합니다.
2차 과제 안내가 메일로 왔고 체험하기를 들어가보니, 데이터 처리 관련 내용이 주를 이뤘다. 1일 남은 상태에서 한다고 해서 무엇이 나아지겠는가? 라고 생각도 들지만, 지푸라기라도 잡는 심정으로 데이터 전처리 문제라도 제대로 풀고자하는 생각에 오늘은 R을 이용하여 SQL과 비슷한 데이터 전처리인 DML을 공부해보고자 한다.
R은 SQL 문법을 직접 지원하지는 않는 것으로 알고 있다. 그래서 sql 문법을 적용하고자 한다면, sqldf
package를 활용해야 한다. 물론 이와 아주 비슷한 것으로 dplyr
이라는 패키지가 있다. 이 모두 데이터 전처리를 위해서 사용하는 것으로 보다 빠르게 원하는 데이터 형식으로 출력할 수 있게 도와준다. 여러 커뮤니티에서 dplyr
패키지의 등장으로 인해 sql이 이제 힘들어질 것이다. 뭐 이런 이야기를 들었는데, 택도 없는 소리다. DB 접근 언어 중 sql 만큼 간편한 query는 본적이 없기 때문에 사라지지 않는다에 한표 건다. 여튼 바로 시작
R에서 dplyr
패키지를 이용할 때 많이 사용하는 연산자가 등장하는 데, 물론 항상 이때만 사용하는건 아니지만, %>%
이다. %>%
의 의미는 앞의 데이터를 이후에 나오는 함수의 인자로 넘겨준다는 것이다. 따라서 앞 인자의 데이터에 들어있는 열의 이름 등을 $
, []
를 사용하지 않아도 쓸 수 있다. 이러한 간편함이 있기 때문에 데이터 전처리에 많이 사용되는거 같다.
18년 상반기에 했던 데이터 마이닝 수업 과제가 기억난다. 그 때 했던 과제에서도 데이터 처리를 모두 %>%
를 사용했다. 아주 좋은 연산자이다. 그럼 상세하게 dplyr
에 어떤 전처리 함수가 들어있는지 정리해보자.
- filter(): 행추출 -> where과 유사하다.
- select(): 열추출 -> select와 유사
- arrange(): 정렬 -> order_by와 유사
- mutate(): 변수 추가 -> select에서 새로운 변수를 만드는 것과 유사
- summarise(): 통계치 산출 -> 이역시 그럼
- group_by(): 집단별 나누기 -> group_by와 유사
- left_join(): 데이터 합치기(열) -> left join, right_join과 유사
- bind_rows(): 데이터 합치기(행)
실습을 위해 ggplot2
패키지에 내장된 mpg
데이터를 기반으로 실습을 진행하겠다.
# 1
install.packages('ggplot2')
library(ggplot2)
mpg = data.frame(ggplot2::mpg)
1번 코드를 이용하여 mpg 데이터를 불러온다. 이제 하나씩 데이터 처리를 해보자.
⌘ 데이터 정제 및 처리 (select, filter, group_by, arrange, mutate, summarise)
1번. 자동차 배기량에 따라 고속도로 연비가 다른지 알아보려고 합니다. displ(배기량)이 4 이하인 자동차 5 이상인 자동차 중 어떤 자동차의 hwy(고속도로 연비)가 평균적으로 더 높은지 알아보세요.
- displ열에서 4이하, 5이상인 자동차를 뽑아야한다.
- 평균 연비를 계산해야한다.
# 2
> mpg4 = mpg %>% filter(displ <= 4)
> mean(mpg4$hwy)
[1] 25.96319
> mpg5 = mpg %>% filter(displ >= 5)
> mean(mpg5$hwy)
[1] 18.07895
간단한 연산이었다.
displ(배기량)이 4 이하인 자동차가 평균 고속도로 연비가 더 높은 것으로 나타났다.
2번. 자동자 제조 회사에 따라 도시 연비가 다른지 알아보려고 합니다. “audi”, “toyota” 중 어느 manufacturer
의 cty
가 평균적으로 더 높은지 알아보세요.
manufacturer
이 아우디 이거나 도요타인 경우를 알아봐야하기 때문에, 행 조건인 filter를 걸어준다. 이후 manufacturer
를 그룹을 지어주고 새로운 통계치를 산출하면 되겠다.
# 3
> cty_mpg_au_to = mpg %>% filter(manufacturer =="audi" | manufacturer=="toyota") %>%
+ group_by(manufacturer) %>% summarise(mean_cty = mean(cty))
> data.frame(cty_mpg_au_to)
manufacturer mean_cty
1 audi 17.61111
2 toyota 18.52941
toyota의 평균 도시 연비가 더 높은 것으로 나타났다.
3번. “chevrolet”, “ford”, “honda” 자동차의 고속도로 연비 평균을 알아보려고 합니다. 이 회사들의 데이터를 추출한 후 hwy 전체 평균을 구해보세요.
manufacturer 이 쉐보레, 포드, 혼다인 경우를 생각해야한다. 이때 |
를 써서 나타내면 코드가 길어지므로 %in%를 사용하여 나타냈다. 이후에는 2번과 같은 코드로 진행된다. |
# 4
> hwy_mpg_ch_fo_ho = mpg %>% filter(manufacturer %in% c('chevrolet', 'ford', 'honda')) %>%
+ group_by(manufacturer) %>% summarise(hwy_mean = mean(hwy))
> data.frame(hwy_mpg_ch_fo_ho)
manufacturer hwy_mean
1 chevrolet 21.89474
2 ford 19.36000
3 honda 32.55556
혼다가 가장 연비가 길었으며 쉐보레, 포드 순이다.
4번. mpg 데이터는 11개 변수로 구성되어 있습니다. 이 중 일부만 추출해 분석에 활용하려고 합니다. mpg 데이터에서 class(자동차 종류), cty(도시 연비) 변수를 추출해 새로운 데이터를 만드세요. 새로 만든 데이터의 일부를 출력해 두 변수로만 구성되어 있는지 확인하세요.
열으 택하는 문제였고 바로 select를 사용하면 된다.
# 5
> mpg_c_c = mpg %>% select(class, cty)
> head(mpg_c_c)
class cty
1 compact 18
2 compact 21
3 compact 20
4 compact 21
5 compact 16
6 compact 18
class, cty 두개의 열만 고르면 되었기 때문에 간단한 문제였다.
5번. 자동차 종류에 따라 도시 연비가 다른지 알아보려고 합니다. 앞에서 추출한 데이터를 이용해 class(자동차 종류)가 “suv”인 자동차와 “compact”인 자동차 중 어떤 자동차의 cty(도시 연비)가 더 높은지 알아보세요.
filter를 통해 class가 suv와 compact에 속하는 경우만 걸러낸다. 이후 class와 cty를 선택하고 그룹을 지어준다. 해당 그룹별로 평균값을 계산해주면 끝!
# 6
> cty_mpg = mpg %>% filter(class %in% c("suv", "compact")) %>%
+ select(class, cty) %>% group_by(class) %>%
+ summarise('cty_mean' = mean(cty))
> data.frame(cty_mpg)
class cty_mean
1 compact 20.12766
2 suv 13.50000
6번. “audi”에서 생산한 자동차 중에 어떤 자동차 모델의 hwy(고속도로 연비)가 높은지 알아보려고 합니다. “audi”에서 생산한 자동차 중 hwy가 1~5위에 해당하는 자동차의 데이터를 출력하세요.
audi인 경우를 filter하고 hwy를 걸러낸 이후 정렬! 앞에 5개를 위해 head를 사용하자. 만약에 desc를 사용하지 않았다면, tail를 써주면 된다. 문제에서는 1위부터 5위까지 차례로 출력을 해줘야하므로 tail을 뽑고 arrange(desc())를 걸어주는 것이 정답일 것이다.
# 7
> mpg %>% filter(manufacturer=="audi") %>% select(hwy) %>%
+ arrange(desc(hwy)) %>% head(5)
hwy
1 31
2 30
3 29
4 29
5 28
7번. mpg 데이터는 연비를 나타내는 변수가 hwy(고속도로 연비), cty(도시 연비), 두 종류로 분리되어 있습니다. 두 변수를 각각 활용하는 대신 하나의 통합 연비 변수를 만들어 분석하려고 합니다.
-1번. mpg 데이터 복사본을 만들고, cty와 hwy를 더한 ‘합산 연비 변수를 추가하세요’
# 8
mpg_1 = mpg %>% mutate(integrate_c_h = hwy + cty)
data.frame(mpg_1)
-2번. 앞에서 만든 ‘합산 연비 변수’를 2로 나눠 ‘평균 연비 변수’를 추가하세요.
# 9
mpg_1 = mpg_1 %>% mutate(mean_c_h = integrate_c_h / 2)
data.frame(mpg_1)
-3번. ‘평균 연비 변수’가 가장 높은 자동차 3종의 데이터를 출력하세요.
# 10
mpg_1 %>% arrange(desc(mean_c_h)) %>% select(mean_c_h) %>% head(5)
-4번. 1~3번 문제를 해결할 수 있는 하나로 연결된 dplyr 구문을 만들어 실행해보세요. 데이터는 복사본 대신 mpg를 이용하세요.
# 11
mpg %>% mutate(mean_c_h = (hwy + cty) / 2) %>% arrange(desc(mean_c_h)) %>% head(5)
8번. mpg 데이터의 class는 ‘suv’, ‘compact’ 등 자동차를 특징에 따라 일곱 종류로 분류한 변수입니다. 어떤 차종의 도시 연비가 높은지 비교해 보려고 합니다. class별 cty 평균을 구해 보세요.
# 12
mpg %>% group_by(class) %>% summarise(mean_cty = mean(cty))
9번. 앞 문제의 출력 결과는 class 값 알파벳 순으로 정렬되어 있습니다. 어떤 차종의 도시 연비가 높은지 쉽게 알아볼 수 있도록 cty 평균이 높은 순으로 정렬해 출력하세요.
# 13
mpg %>% group_by(class) %>% summarise(mean_cty = mean(cty)) %>% arrange(desc(mean_cty))
10번. 어떤 회사 자동차의 hwy(고속도로 연비)가 가장 높은지 알아보려고 합니다. hwy 평균이 가장 높은 회사 세 곳을 출력하세요.
# 14
mpg %>% group_by(manufacturer) %>% summarise(mean_hwy = mean(hwy)) %>% arrange(desc(mean_hwy)) %>% head(3)
11번. 어떤 회사에서 “compact”(경차) 차종을 가장 많이 생산하는지 알아보려고 합니다. 각 회사별 “compact”차종 수를 내림차순으로 정렬해보세요.
# 15
mpg %>% filter(class=="compact") %>% group_by(manufacturer) %>%
summarise('count'=n()) %>% arrange(desc(count))
⌘ 데이터 합치기 (join, bind)
테이블을 여러 개 합쳐서 분석해야하는 경우, 예를 들어 중간 + 기말 데이터를 합쳐서 분석해야 하는 경우 데이터를 합쳐야한다. 따로따로 분석하기 보다 한번에 모아서 보는 것이 훨씬 편한 경우에는 이러한 join(열)이나 bind(행)를 사용하여 테이블 하나로 합치자.
가로 합치기(열로 합치기)
# 16
test1 = data.frame(id=c(1, 2, 3, 4, 5),
midterm = c(60, 80, 70, 90, 85))
test2 = data.frame(id=c(1, 2, 3, 4, 5),
final = c(70, 83, 65, 95, 80))
total = left_join(test1, test2, by="id")
total
세로 합치기(행으로 합치기)
# 17
test1 = data.frame(id=c(1, 2, 3, 4, 5),
test = c(60, 80, 70, 90, 85))
test2 = data.frame(id=c(6, 7, 8, 9, 10),
test = c(70, 83, 65, 95, 80))
total = bind_rows(test1, test2)
total
사실 위의 경우 R에서는 rbind와 cbind라는 내장 함수를 제공하고 있다. 하지만, 이 함수 내에 id와 같이 키 값을 이용한 정렬 기능없다. 따라서 R에서는 merge함수를 제공하고 있다. merge함수에서는 외래키를 이용한 join을 제공하며, 이를 위한 키는 join_left함수와 같이 by라는 옵션 또는 인자를 제공한다. 만약에 outer join을 하고 싶다면, all=TRUE 옵션을 달아주면 되겠다. 이때 all 인자의 기본값(default)은 FALSE이다.
연습문제
미국 동북중부 437개 지역의 인구통계 정보를 담고 있는 midwest 데이터를 사용해 데이터 분석 문제를 해결하자. midwest는 ggplot2 패키지에 내장되어 있다.
# 18
library(ggplot2)
midwest = as.data.frame(ggplot2::midwest)
1번. popadults는 해당 지역의 성인 인구. poptotal은 전체 인구를 나타냅니다. midwest데이터에 ‘전체 인구 대비 미성년 인구 백분율’ 변수를 추가하세요.
# 19
midwest %>% mutate(전체_인구_대비_미성년_인구_백분율 = (poptotal - popadults)/poptotal*100)
2번. 미성년 인구 백분율이 가장 높은 상위 5개 country(지역)의 미성년 인구 백분율을 출력하세요.
# 20
midwest %>% arrange(desc(전체_인구_대비_미성년_인구_백분율)) %>%
select(county, 전체_인구_대비_미성년_인구_백분율) %>% head(5)
3번. 분류표의 기준에 따라 미성년 비율 등급 변수를 추가하고, 각 등급에 몇 개의 지역이 있는지 알아보세요.
Large: 40% 이상
middle: 30 ~ 40% 미만
small: 30% 미만
간단하게 ifelse구분으로 데이터를 조작하면 된다. R의 if문 중 개인적으로 가장 사용하기 편한게 ifelse 구문이라 생각한다.
# 21
grade_midwest = midwest %>% mutate(grade=ifelse(전체_인구_대비_미성년_인구_백분율>=40, 'large',
ifelse(전체_인구_대비_미성년_인구_백분율>=30,'middle', 'small'))) %>%
select(grade)
table(grade_midwest)
grade_midwest
large middle small
32 396 9
4번. popasian은 해당 지역의 아시아인 인구를 나타냅니다. ‘전체 인구 대비 아시아인 인구 백분율’ 변수를 추가하고 10개 지역의 state(주), country(지역), 아시아인 인구 백분율을 출력하세요.
# 22
midwest %>% mutate(전체_인구_대비_아시아인_인구_백분율=(popasian)/poptotal*100) %>%
select(county, state, 전체_인구_대비_아시아인_인구_백분율) %>%
arrange(전체_인구_대비_아시아인_인구_백분율) %>%
head(10)
이상 정리 끝!