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문제를 해결할 필요가 있다.

  1. 데이터 삭제: 가장 쉽게 사용될 수 있는 방법이다. 식별가능한 나이대의 행을 삭제한다면 privacy문제를 어느정도 해결할 수 있다. 하지만 이 방법은 특정 계층에 대한 정보를 전혀 제공하지 않기 때문에 utility측면에서 큰 마이너스 요인이 된다.

  2. 데이터 범주화: 연령대의 구간을 정해 범주화하는 것이다. 이를 통해 특정 계층의 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값 또한 이전보다 감소했다.