1. Compute k-anonymity and l-diversity for each record.
#install.packages('synthpop')
require(synthpop)
## Loading required package: synthpop
## Find out more at https://www.synthpop.org.uk/
vars = c('sex','age','marital', 'income', 'ls')
#marital : Marital status / ls : Perception of life as a whole
SD_2011_sub = SD2011[,vars]
ods = SD_2011_sub[which(SD_2011_sub$income>0),]
(a) Implement the R code with a seed=”student id”.
sds.default = syn(ods, seed=2015122055)
## Synthesis
## -----------
## sex age marital income ls
sds=sds.default$syn
(b) Let ‘sex’ and ‘age’ be the key variables and ‘ls’ be the sensitive variable.
(c) Sort your synthetic data in order of ‘sex’, ’age’ and ’ls’.
library(plyr)
sds = arrange(sds, sex,age,ls) # 데이터 정렬
(d) Report the first 20 data lines including k-anonymity and l-diversity
# synthetic data 의k-anonymity and l-diversity열 부여
sds$anonymity = NA
sds$diversity = NA
for (i in unique(sds$sex)) {
for (j in unique(sds$age)) {
k = length(sds[sds$sex==i & sds$age==j,'anonymity'])
sds[sds$sex==i & sds$age==j,'anonymity'] = rep(k,k)
l = length(unique(sds[sds$sex==i & sds$age==j,'ls']))
sds[sds$sex==i & sds$age==j,'diversity'] = rep(l,k)
}
}
sds[1:20,]
## sex age marital income ls anonymity diversity
## 1 MALE 18 SINGLE 1000 PLEASED 14 3
## 2 MALE 18 MARRIED 2000 PLEASED 14 3
## 3 MALE 18 SINGLE 360 PLEASED 14 3
## 4 MALE 18 SINGLE 360 PLEASED 14 3
## 5 MALE 18 SINGLE 500 PLEASED 14 3
## 6 MALE 18 SINGLE 120 PLEASED 14 3
## 7 MALE 18 MARRIED 2000 PLEASED 14 3
## 8 MALE 18 MARRIED 2700 PLEASED 14 3
## 9 MALE 18 SINGLE 500 PLEASED 14 3
## 10 MALE 18 SINGLE 300 MOSTLY SATISFIED 14 3
## 11 MALE 18 SINGLE 300 MOSTLY SATISFIED 14 3
## 12 MALE 18 SINGLE 300 MOSTLY SATISFIED 14 3
## 13 MALE 18 SINGLE 500 MIXED 14 3
## 14 MALE 18 SINGLE 300 MIXED 14 3
## 15 MALE 19 MARRIED 2700 PLEASED 5 2
## 16 MALE 19 SINGLE 2000 PLEASED 5 2
## 17 MALE 19 SINGLE 150 MOSTLY SATISFIED 5 2
## 18 MALE 19 MARRIED 1000 MOSTLY SATISFIED 5 2
## 19 MALE 19 SINGLE 660 MOSTLY SATISFIED 5 2
## 20 MALE 20 MARRIED 1800 PLEASED 14 2
k-anonymity열과 l-diversity열을 추가한 최종 데이터는 위와같다.
20개의 행을 살펴보면 성별이 전부 남성으로 이루어져있으며 18세가 대부분이다.k값은 모두 3이상으로 적절한 값을 가진다.
하지만 남성19세,20세의 l값이 작아 식별위험성이 존재한다.
2. Evaluate your synthetic data with data utility and privacy. Is it good enough?
1번에서 얻은 데이터를 바탕으로 데이터의 utility 와 privacy를 파악해보았다.
Check data utility
summary(ods)
## sex age marital income
## MALE :1661 Min. :17.00 SINGLE : 644 Min. : 100.0
## FEMALE:2053 1st Qu.:37.00 MARRIED :2355 1st Qu.: 970.5
## Median :53.00 WIDOWED : 504 Median : 1350.0
## Mean :51.84 DIVORCED : 176 Mean : 1641.5
## 3rd Qu.:64.00 LEGALLY SEPARATED : 6 3rd Qu.: 2000.0
## Max. :97.00 DE FACTO SEPARATED: 21 Max. :16000.0
## NA's : 8
## ls
## PLEASED :1403
## MOSTLY SATISFIED :1264
## MIXED : 653
## MOSTLY DISSATISFIED: 230
## DELIGHTED : 107
## (Other) : 52
## NA's : 5
summary(sds)
## sex age marital income
## MALE :1663 Min. :17.00 SINGLE : 672 Min. : 100
## FEMALE:2051 1st Qu.:37.00 MARRIED :2354 1st Qu.: 940
## Median :54.00 WIDOWED : 485 Median : 1300
## Mean :51.88 DIVORCED : 169 Mean : 1625
## 3rd Qu.:64.00 LEGALLY SEPARATED : 6 3rd Qu.: 2000
## Max. :96.00 DE FACTO SEPARATED: 20 Max. :15000
## NA's : 8
## ls anonymity diversity
## PLEASED :1386 Min. : 1.00 Min. :1.000
## MOSTLY SATISFIED :1286 1st Qu.:24.00 1st Qu.:4.000
## MIXED : 667 Median :30.00 Median :5.000
## MOSTLY DISSATISFIED: 222 Mean :32.26 Mean :4.679
## DELIGHTED : 99 3rd Qu.:40.00 3rd Qu.:5.000
## (Other) : 52 Max. :69.00 Max. :8.000
## NA's : 2
Synthetic datad와 Original data의 전체 열에 대한 요약값은 위와 같다. 모든 변수에서 비율, 중간값 등 Original data와 굉장히 비슷한 특징을 가지고 있다.
test1 <- cbind(table(sds$sex),table(ods$sex))
colnames(test1)=c('Synthetic data','Original data')
barplot(test1,beside=T,col=c("darkblue","red"),legend =c('Male','Female'))
두 데이터의 성별 비율이 거의 일치하는 것으로 보인다.
test2 <- cbind(table(sds$age),table(ods$age))
## Warning in cbind(table(sds$age), table(ods$age)): number of rows of result is
## not a multiple of vector length (arg 1)
colnames(test2)=c('Synthetic data','Original data')
barplot(test2,beside=T, col=c('skyblue'), legend=c('age'))
age의 경우 약간의 차이는 보이나 전체적인 분포의 모양은 매우 유사하게 나타나고 있다.
test1 <- rbind(table(sds$ls),table(ods$ls))
rownames(test1)=c('Synthetic data','Original data')
barplot(test1,beside=T,col=c("darkblue",'red'),legend=c('Synthetic data','Original data'))
추가로 sensitive variable인 ls의 비율도 거의 일치한다.
par(mfcol=c(1, 4))
boxplot(age~sex, data=ods, main='Original data', col='powderblue')
boxplot(age~sex, data=sds, main='Synthetic data', col='mistyrose')
boxplot(income~sex, data=ods, main='Original data', col='powderblue')
boxplot(income~sex, data=sds, main='Synthetic data', col='mistyrose')
성별에 따른 나이, 수입의 boxplot을 통해 몇몇 아웃라이어를 제외하고는 비슷한 데이터 분포를 가지고 있다는 것을 알 수 있다.
paste('Original data의 age와 income 공분산 : ',round(cov(ods$age,ods$income),2),' , Synthetic data의 age와 income 공분산 : ',round(cov(sds$age,sds$income),2))
## [1] "Original data의 age와 income 공분산 : -2702.43 , Synthetic data의 age와 income 공분산 : -2778.85"
table(ods$marital,ods$ls)
##
## DELIGHTED PLEASED MOSTLY SATISFIED MIXED
## SINGLE 20 208 225 133
## MARRIED 79 1050 800 326
## WIDOWED 7 124 174 132
## DIVORCED 1 17 54 50
## LEGALLY SEPARATED 0 0 1 1
## DE FACTO SEPARATED 0 1 8 9
##
## MOSTLY DISSATISFIED UNHAPPY TERRIBLE
## SINGLE 52 6 0
## MARRIED 73 14 9
## WIDOWED 55 8 3
## DIVORCED 43 8 3
## LEGALLY SEPARATED 3 0 1
## DE FACTO SEPARATED 3 0 0
table(sds$marital,sds$ls)
##
## DELIGHTED PLEASED MOSTLY SATISFIED MIXED
## SINGLE 16 220 247 130
## MARRIED 78 1027 802 347
## WIDOWED 4 120 177 124
## DIVORCED 1 16 47 55
## LEGALLY SEPARATED 0 1 1 0
## DE FACTO SEPARATED 0 2 8 8
##
## MOSTLY DISSATISFIED UNHAPPY TERRIBLE
## SINGLE 54 5 0
## MARRIED 75 15 8
## WIDOWED 47 11 2
## DIVORCED 41 7 2
## LEGALLY SEPARATED 3 1 0
## DE FACTO SEPARATED 1 1 0
마지막으로 marital에 따른 ls결과 값을 확인해보았다. 예상대로 비율이 거의 일치하고 있다.
Check data privacy
par(mfcol=c(1, 1))
barplot(table(sds$anonymity), main='K-anonymity')
summary(sds$anonymity)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.00 24.00 30.00 32.26 40.00 69.00
sum(sds$anonymity < 4)
## [1] 13
K-anonymity의 값이 대부분 3을 넘고 있음을 확인할 수 있다. 하지만 3이하의 값을 갖는 13개의 행이 존재한다.
unique(arrange(sds[sds$anonymity < 4,c('sex','age','anonymity')],anonymity))
## sex age anonymity
## 1 MALE 90 1
## 2 FEMALE 91 1
## 3 FEMALE 96 1
## 4 MALE 91 2
## 6 FEMALE 19 2
## 8 FEMALE 17 3
## 11 FEMALE 18 3
남성 90세, 여성 91세와 96세에서 K값이 1이다. 이는 개인의 프라이버시가 지켜지지 못하고 있다. 또한, 남자 91세, 여자 17~19세에서 낮은 K값을 가지고 있어 다른 연령대에 비해 특정될 위험이 있다. 즉, 90세 이상의 노인계층과 20세 이하의 청소년 계층 k값이 낮은편으로 위험성이 존재하며 이를 해결해야 할 것이다.
unique(sds$ls)
## [1] PLEASED MOSTLY SATISFIED MIXED
## [4] MOSTLY DISSATISFIED DELIGHTED UNHAPPY
## [7] TERRIBLE <NA>
## 7 Levels: DELIGHTED PLEASED MOSTLY SATISFIED MIXED ... TERRIBLE
barplot(table(sds$diversity), main='l-diversity')
summary(sds$diversity)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 4.000 5.000 4.679 5.000 8.000
sum(sds$diversity < 3)
## [1] 56
l-diversity 또한 대부분 3을 넘고 있다. 아래와 같이 3을 넘지 못하는 56개의 행이 존재한다.
unique(arrange(sds[sds$diversity < 3,c('sex','age','diversity')],diversity))
## sex age diversity
## 1 MALE 85 1
## 6 MALE 90 1
## 7 MALE 91 1
## 9 FEMALE 91 1
## 10 FEMALE 96 1
## 11 MALE 19 2
## 16 MALE 20 2
## 30 MALE 86 2
## 34 MALE 88 2
## 39 FEMALE 17 2
## 42 FEMALE 18 2
## 45 FEMALE 19 2
## 47 FEMALE 87 2
## 52 FEMALE 90 2
K값과 마찬가지로 20세 이하, 90세 이상의 데이터에서 낮은 l값을 갖고 있다. 또한, l값의 경우 k보다 더 다양한 연령대에서 2 이하의 값을 가지며 해당 성별, 나이대의 삶 만족도가 특정될 위험성이 크다.
최종평가
개별 변수 및 변수 간의 관계를 확인했을 때 기존데이터와 비슷한 분포, 비율을 띄고 있어 Synthetic data의 utility는 굉장히 좋다고 볼 수 있다. 이에 반해 특정 연령대에서 k,l값이 낮게 나타나 식별위험이 존재하기 때문에 privacy는 보완할 필요성이 있다. 현재 데이터는 utility가 매우 좋기 때문에 둘 간의 trade off를 통해 privacy 측면을 높여야 할 것이다.
3. Discuss how you can modify or update the above algorithm. (Tip: recommend to review the methodology implemented in synthpop and see the lecture note again).
sds.default$method
## sex age marital income ls
## "sample" "cart" "cart" "cart" "cart"
Synthetic data의 각 변수 생성에 사용된 방법은 위와 같다. synthpop에서 다양한 방식을 제공하는 만큼 이를 통해 기존 데이터의 privacy 문제를 해결할 수 있을 것이라 생각하게 되었고 여러 기법을 이용하여 변수를 생성해보았다. 하지만 default방식에서 얻은 data와 큰 차이가 없었으며 여전히 privacy문제가 존재했다.
barplot(table(ods$age))
나이에서 privacy문제가 발생하고 있기에 Original data의 나이대 분포를 확인해보았다. 위 plot처럼 청소년 계층, 노인계층으로 갈수록 데이터의 수가 적은 것을 확인할 수 있다. 즉, 이 계층에 대한 privacy문제를 해결할 필요가 있다.
데이터 삭제: 가장 쉽게 사용될 수 있는 방법이다. 식별가능한 나이대의 행을 삭제한다면 privacy문제를 어느정도 해결할 수 있다. 하지만 이 방법은 특정 계층에 대한 정보를 전혀 제공하지 않기 때문에 utility측면에서 큰 마이너스 요인이 된다.
데이터 범주화: 연령대의 구간을 정해 범주화하는 것이다. 이를 통해 특정 계층의 privacy를 보장하게 된다. 하지만 이미 privacy가 보장된 정보들은 이 과정을 통해 utility가 떨어진다. 그러므로 특정 구간에만 데이터 범주화를 적용하는 것이 가장 적절한 방법이라고 생각한다. 20세 이하, 90세 이상은 정보들에만 20-, 90+로 처리한다면 전체를 범주화하는 것보다 높은 utility를 가짐과 동시에 privacy도 보장할 수 있을 것이다.
for (i in 17:19) {
sds[sds$age==i,'age']=20
}
for (i in 90:97) {
sds[sds$age==i,'age']=90
}
sds$anonymity = NA
sds$diversity = NA
for (i in unique(sds$sex)) {
for (j in unique(sds$age)) {
k = length(sds[sds$sex==i & sds$age==j,'anonymity'])
sds[sds$sex==i & sds$age==j,'anonymity'] = rep(k,k)
l = length(unique(sds[sds$sex==i & sds$age==j,'ls']))
sds[sds$sex==i & sds$age==j,'diversity'] = rep(l,k)
}
}
barplot(table(sds$anonymity), main='K-anonymity')
barplot(table(sds$diversity), main='l-diversity')
R을 통해 17~20, 90~97세 구간에 대해 20, 90을 부여한 결과 이전보다 나은 privacy를 가지는 데이터를 생성할 수 있었다. 3미만의 k값이 완전히 사라졌으며 1,2 값을 가지는 l값 또한 이전보다 감소했다.