학력고사로 대학을 입학한 세대가 다시 대학입학 관련 문제를 다시 보게 되는 경우는 아마도 자식이 대학을 갈 때가 될 때인지 싶다. 학력고사를 통해 나온 점수에 맞춰 대학에 진학을 했는데 20~30년이 지난 후에 수능문제는 얼마나 달라졌는지 데이터 과학 접근법을 취해 데이터로 살펴보자.
EBS 풀서비스 웹사이트에서 문제, 정답표, 해설지 뿐만 아니라 다양한 통계정보를 얻을 수 있다. 먼저 국영수에 대한 평균과 표준편차를 추출하여 정형데이터로 만들어보자.
수능시험 등급컷의 경우 “국수영한”, “사회”, “과학”, … 와 같이 해당 과목에 등급을 모두 보여줘야 되서 POST
방식으로 해당 인자를 넘겨줘야 수능등급 표를 얻을 수 있다. HTML 웹페이지에서 과목 평균, 표준편차를 얻어내고 등급표를 하나의 데이터프레임으로 담아 후속 분석을 위한 준비를 한다.
library(tidyverse)
library(rvest)
library(xml2)
library(httr)
# Base URL
"http://www.ebsi.co.kr/ebs/xip/xipa/retrieveGrdCutList.ebs"
base_url <-
# 국영수 ----
"subjectId=60001,63004,80003,80003,63004,61007,60001,61001,61001,61007&irecord=202012033&ord=1"
국영수 <-# key_subject <- "subjectId=60001,63004,80003,80003,63004,61007,60001,61001,61001,61007&irecord=202012033&ord=1"
# 사회 ----
"subjectId=141,142,140112,66002,66001,63003,63002,63001,146&irecord=202012033&ord=2"
사회 <-# 과학 ----
"subjectId=154,155,156,159,158,140116,140115,157&irecord=202012033&ord=3"
과학 <-
glue::glue("{base_url}?{`국영수`}")
key_subject_url <-
Sys.setlocale("LC_ALL", "C")
[1] "C"
key_subject_url %>%
key_subject_html <- read_html(encoding = 'EUC-KR')
## 과목별 등급표 -----
list()
subject_list <-
for(i in 1:5) {
key_subject_html %>%
subject_list[[i]] <- html_node(xpath = glue::glue("/html/body/section[{i}]/table")) %>%
html_table(fill = TRUE)
}
Sys.setlocale("LC_ALL", "Korean")
[1] "LC_COLLATE=Korean_Korea.949;LC_CTYPE=Korean_Korea.949;LC_MONETARY=Korean_Korea.949;LC_NUMERIC=C;LC_TIME=Korean_Korea.949"
subject_list %>%
subject_rank_tbl <- enframe(name = "순", "등급표")
## 과목 통계 -----
subject_rank_tbl
# A tibble: 5 x 2
순 등급표
<int> <list>
1 1 <df[,5] [8 x 5]>
2 2 <df[,5] [8 x 5]>
3 3 <df[,5] [8 x 5]>
4 4 <df[,5] [8 x 5]>
5 5 <df[,5] [8 x 5]>
## 과목 통계 -----
key_subject_html %>%
key_subject_name_v <- html_nodes(css = 'h2') %>%
html_text() %>%
str_trim()
key_subject_html %>%
key_subject_stat_v <- html_nodes(css = 'p') %>%
html_text() %>%
str_remove_all("\n\t\t\t") %>%
str_remove_all("\n\t\t") %>%
str_trim()
tibble(과목명 = key_subject_name_v, 통계=key_subject_stat_v) %>%
key_subject_tbl <- separate(통계, into = c("평균", "표준편차"), sep = "표준편차") %>%
mutate(평균 = parse_number(평균),
parse_number(표준편차))
표준편차 =
key_subject_tbl
# A tibble: 5 x 3
과목명 평균 표준편차
<chr> <dbl> <dbl>
1 국어 59.0 18.6
2 수학가형 57.6 23.1
3 수학나형 49.6 27.2
4 영어 NA NA
5 한국사 NA NA
# 교과목 통계 + 등급표
bind_cols(key_subject_tbl, subject_rank_tbl)
key_tbl <-
key_tbl
# A tibble: 5 x 5
과목명 평균 표준편차 순 등급표
<chr> <dbl> <dbl> <int> <list>
1 국어 59.0 18.6 1 <df[,5] [8 x 5]>
2 수학가형 57.6 23.1 2 <df[,5] [8 x 5]>
3 수학나형 49.6 27.2 3 <df[,5] [8 x 5]>
4 영어 NA NA 4 <df[,5] [8 x 5]>
5 한국사 NA NA 5 <df[,5] [8 x 5]>
데이터의 통계 정보가 있어 정규분포를 가정하고 평균과 표준편차를 각 과목별 등급을 표시하여 시각화를 한다.
key_tbl %>%
key_viz_tbl <- select(-순) %>%
mutate(dnorm_data = purrr::map2(평균, 표준편차,
~tibble(x = seq(0, 110, length.out = 100),
y = dnorm(x, .x, .y)))) %>%
na.omit()
%>%
key_viz_tbl unnest(등급표) %>%
ggplot() +
geom_vline(aes(xintercept = 원점수, color = 과목명)) +
geom_line(data = key_viz_tbl %>% unnest(dnorm_data), aes(x, y, color = 과목명)) +
facet_wrap(~과목명, ncol=1) +
theme_light() +
theme(legend.position = "none") +
labs(x="원점수", y="밀도",
title = "2021년 수능 등급 분포")
평균과 표준편차 정보가 확인된 국어와 수학가형, 수학나형에 대한 성적분포를 비교해보자.
%>%
key_viz_tbl unnest(dnorm_data) %>%
ggplot(aes(x, y, color = 과목명)) +
geom_line() +
scale_x_continuous(limits = c(0,110)) +
theme_light() +
theme(legend.position = "top") +
labs(x="원점수", y="밀도",
title = "2021년 수능 국어, 수학 성적분포 비교")
데이터 과학자 이광춘 저작
kwangchun.lee.7@gmail.com