factor를 이용해 식별값을 코드화하기
대량의 데이터를 사용할 때 가끔 개별 행(레코드)의 고유한 이름이 기록되어 있는 경우가 있을 것이다. 예를 들어 고객 이름이라던지 특정 지역명, 특정 지점명등과 같이 개별 이름이 코드화 되어 있지 않고 사람이 인식할 수 있는 문자 형태로 기록된 데이터를 사용하여 분석을 할 때는 이 이름들을 드러내지 않도록 처리해야 할 것이다.
필자는 교육통계 데이터를 주로 다루는데, 이 데이터에는 대부분 학교명이 들어 있는 경우가 많다. 하지만 이 학교명을 그대로 사용하여 분석하면 특정 학교가 드러나게 되므로 학교 이름을 보통 코드화하여 분석해야 한다. 따라서 분석을 시작하기 전에 데이터를 전체적으로 확인하여 데이터의 식별이 가능한 데이터가 포함되어 있는지 먼저 확인해야 하고 식별가능한 변수가 있다면 이를 식별이 불가능하도록 가명화, 익명화 방법을 사용해 비식별화 처리를 해야 한다. 하지만 바꿀 데이터가 한두개 정도라면 금방 바꿀 수 있겠지만 수백, 수천개의 데이터라면 어떻게 바꿀수 있겠는가?
본 포스트에서는 factor를 사용한 데이터 비식별화 처리 방법에 대해 알아보겠다.
이 포스트에서 사용하는 데이터는 ’연도별, 지역별, 학교급별, 학생수, 학급수, 학교수 Plot - 변수에 따른 배경색 변화 in R’에서 사용한 한국교육개발원 교육통계 홈페이지의 시도별 교육통계 주제별 자료 연도별 모음(1999-2021)를 사용하였다.
library(readxl)
library(tidyverse)
df <- read_excel('./주요-01 유초 연도별 시도별 교육통계 모음(1999-2021)_210901.xlsx', skip = 3, na = '-', sheet = '01 개황', col_types = c('numeric', 'text', 'text', rep('numeric', 48)), col_names = F)
df_adj <- df |>
select(1:3, 5, 11, 17, 21) |>
rename('year' = '...1', 'province' = '...2', 'sch_class' = '...3', 'class_total' = '...5', 'stu_total' = '...11', 'teach_total' = '...17', 'teach_tmp_total' = '...21') |>
filter(province != '전국', sch_class == c('유치원', '초등학교', '중학교', '고등학교'))
glimpse(df_adj)
## Rows: 356
## Columns: 7
## $ year <dbl> 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, ~
## $ province <chr> "서울", "서울", "서울", "서울", "부산", "부산", "부산"~
## $ sch_class <chr> "유치원", "초등학교", "중학교", "고등학교", "유치원", ~
## $ class_total <dbl> 3376, 20222, 10970, 10271, 1367, 8107, 4143, 4207, 900~
## $ stu_total <dbl> 92681, 753606, 390220, 503096, 39807, 294705, 158297, ~
## $ teach_total <dbl> 4536, 24299, 19672, 20604, 2161, 9785, 7465, 8542, 109~
## $ teach_tmp_total <dbl> 27, 101, 569, 163, 18, 100, 350, 384, 4, 48, 126, 59, ~
head(df_adj)
## # A tibble: 6 x 7
## year province sch_class class_total stu_total teach_total teach_tmp_total
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 1999 서울 유치원 3376 92681 4536 27
## 2 1999 서울 초등학교 20222 753606 24299 101
## 3 1999 서울 중학교 10970 390220 19672 569
## 4 1999 서울 고등학교 10271 503096 20604 163
## 5 1999 부산 유치원 1367 39807 2161 18
## 6 1999 부산 초등학교 8107 294705 9785 100
이 데이터 중에 만약 지역명을 드러내지 않고 지역1, 지역2와 같이 코딩하려면 어떻게 해야할까?
factor를 사용하여 지역명을 코드로 만들어본다.
우선 df_adj
데이터프레임의 지역명이 저장된 province
열을 factor
로 변환한다.
df_adj$province <- as.factor(df_adj$province)
glimpse(df_adj)
## Rows: 356
## Columns: 7
## $ year <dbl> 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, ~
## $ province <fct> 서울, 서울, 서울, 서울, 부산, 부산, 부산, 부산, 인천, ~
## $ sch_class <chr> "유치원", "초등학교", "중학교", "고등학교", "유치원", ~
## $ class_total <dbl> 3376, 20222, 10970, 10271, 1367, 8107, 4143, 4207, 900~
## $ stu_total <dbl> 92681, 753606, 390220, 503096, 39807, 294705, 158297, ~
## $ teach_total <dbl> 4536, 24299, 19672, 20604, 2161, 9785, 7465, 8542, 109~
## $ teach_tmp_total <dbl> 27, 101, 569, 163, 18, 100, 350, 384, 4, 48, 126, 59, ~
위와 같이 province
열이 character 타입에서 factor 타입으로 변경되었다. 그럼 factor 타입을 정수형으로 바꿔보자.
df_adj$province <- as.integer(df_adj$province)
glimpse(df_adj)
## Rows: 356
## Columns: 7
## $ year <dbl> 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, ~
## $ province <int> 9, 9, 9, 9, 8, 8, 8, 8, 12, 12, 12, 12, 7, 7, 7, 7, 1,~
## $ sch_class <chr> "유치원", "초등학교", "중학교", "고등학교", "유치원", ~
## $ class_total <dbl> 3376, 20222, 10970, 10271, 1367, 8107, 4143, 4207, 900~
## $ stu_total <dbl> 92681, 753606, 390220, 503096, 39807, 294705, 158297, ~
## $ teach_total <dbl> 4536, 24299, 19672, 20604, 2161, 9785, 7465, 8542, 109~
## $ teach_tmp_total <dbl> 27, 101, 569, 163, 18, 100, 350, 384, 4, 48, 126, 59, ~
위와 같이 province
열이 문자에서 숫자로 코딩이 되었다. 그런데 너무 숫자만 있으면 보기가 어려우니 ’지역+숫자’의 형태를 가지도록 코드를 만드는게 좋을 듯 하고 지역명은 총 17개이기 때문에 숫자는 두자리로 표현하는 게 좋겠다.
다음과 코드를 만들어 줄 수 있다.
df_adj$province <- paste0('지역', sprintf('%02d', df_adj$province))
head(df_adj, 10)
## # A tibble: 10 x 7
## year province sch_class class_total stu_total teach_total teach_tmp_total
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 1999 지역09 유치원 3376 92681 4536 27
## 2 1999 지역09 초등학교 20222 753606 24299 101
## 3 1999 지역09 중학교 10970 390220 19672 569
## 4 1999 지역09 고등학교 10271 503096 20604 163
## 5 1999 지역08 유치원 1367 39807 2161 18
## 6 1999 지역08 초등학교 8107 294705 9785 100
## 7 1999 지역08 중학교 4143 158297 7465 350
## 8 1999 지역08 고등학교 4207 198384 8542 384
## 9 1999 지역12 유치원 900 25563 1098 4
## 10 1999 지역12 초등학교 5763 240782 6886 48
sprintf()
는 원래 C에서 사용되던 함수이다. 자세한 함수의 사용방법은 sprintf 사용설명서를 참조하라.
비식별화 패키지(anonymizer
)를 이용해 식별값을 코드화하기
최근 빅데이터 활용에는 개인정보의 비식별화 기법이 매우 중요한 기법이다. 따라서 R에서도 개별 식별값을 비식별화하는 몇 개의 패키지를 제공한다.
anonymizer
패키지에서 제공하는 anonymizer()
는 암호화 방법 중 하나인 솔트(salt) 기법과 해시 기법을 사용하여 데이터를 익명화(anonymization)하는 함수이다. anonymizer
패키지는 cran에 등록되어 있지 않아 다음과 같이 설치할 수 있다.
if (packageVersion("devtools") < 1.6) {
install.packages("devtools")
}
devtools::install_github("paulhendricks/anonymizer")
anonymizer()
를 사용하여 비식별화하는 방법은 다음과 같다.
library(anonymizer)
df_adj$province.암호화 <- anonymize(df_adj$province, .algo = "crc32")
df_adj |>
select(2, 8) |>
head(10)
## # A tibble: 10 x 2
## province province.암호화
## <chr> <chr>
## 1 지역09 9e0af0b6
## 2 지역09 9e0af0b6
## 3 지역09 9e0af0b6
## 4 지역09 9e0af0b6
## 5 지역08 55562313
## 6 지역08 55562313
## 7 지역08 55562313
## 8 지역08 55562313
## 9 지역12 52ba0bc1
## 10 지역12 52ba0bc1
다른 값으로 대체하는 패키지
또 하나의 비식별화 처리는 허위(fake) 값으로 대체하는 것이다. R에서는 이와 같이 허위 값으로 개인 데이터를 대체하는 generator
패키지를 제공한다. generator
패키지에서는 개인 식별자의 형태에 따라 허위 값을 생성하는 다음과 같은 몇 개의 함수를 제공한다.
r_full_names()
: 허위 이름을 생성하는 함수r_date_of_births()
: 허위 생년월일을 생성하는 함수r_national_identification_numbers()
: 허위 국가 인식 번호를 생성하는 함수r_phone_numbers()
: 허위 전화번호를 생성하는 함수
위의 함수외에도 몇가지 함수를 더 제공하는데 이는 패키지의 설명서를 참조하라.
library(generator)
r_full_names(10)
## [1] "Tawna Thompson" "Lynn Paucek" "Gregory Pouros" "Isreal Bogan"
## [5] "Towanda Torphy" "Maia Fay" "Lane Stanton" "Parker Streich"
## [9] "Abel Batz" "Jerrod Borer"
r_phone_numbers(10)
## [1] "9769849762" "7326892596" "6133867946" "8731458196" "4756541586"
## [6] "1977362936" "7432918254" "7856813297" "1566944157" "1363763941"
'데이터 전처리' 카테고리의 다른 글
R-Studio 단축키 (0) | 2021.12.26 |
---|---|
여러 열의 천단위 구분자 없애기 in R (0) | 2021.12.16 |
클립보드(clipboard) 데이터 읽고 쓰기 in R (0) | 2021.10.16 |
데이터프레임의 열을 벡터로 변환 (0) | 2021.08.21 |
데이터 개수 세기(도수분포)와 구간 나누기 (0) | 2021.07.01 |
댓글