1 미국대선 여론조사 1 2

제45대 미국 대통령을 선출하는 선거에서 많은 언론에서 예측한 바와 다르게 공화당 도널드 트럼프 후보가 민주당 힐러리 클린턴 후보를 누르고 당선되었다. 이를 두고 트럼프 후보 당선을 정확히 예측한 인공지능(AI) 사례를 들며 기존 예측기법에 대한 문제점 제기 및 새로운 시대의 도래를 언급하고 있다. 이에 앞서 지금과 동일한 상황이 미국에서 여러번 있어와서 새삼스러운 것은 아니다.

  • 1916년 대선: 우편 설문조사를 바탕으로 민주당 우드로 윌슨 후보 당선 예측한
    • 리터리리 다이제스트는 1936년 대통령 예측에서 실패
    • 1천만명 유권자를 대상으로 설문조사를 실시했으나 표본의 대표성에 문제가 있음
    • 주소 확보가 용이한 구독자, 자동차 등록부, 전화번호부 등 공화당 성향 유권자에 집중
  • 1936년 대선: 조기 갤럽의 ’미국공공여론연구소’에서 5만명 표본으로 프랭클린 루스벨트 당선 예측
    • 인구학적 분포에 대응되는 표본 추출 기법 차용
    • 1948년 선거일보다 3주 앞서 당선 후보 예측한 것이 화근이 되어, ’Dewey defeats truman’이라는 ’역사적 오보’를 남김.
  • 패널 조사: 장기간의 추적분석과 정치 성향이 표본 추출에 내재된 보다 정교한 여론조사 기법이 등장
    • 2016년 미국 대선에서 non-ignorable nonresponse 문제를 해결하지 못해 예측에 실패함.
    • 인공지능 인도 벤처기업 제니크.ai(Genic.ai) 인공지능 모그IA(MogIA)는 빅데이터 분석을 통해 10월부터 트럼프 승리 예측

결측값 구분 3

  • MCAR(Missing Completely At Random): 모든 정보가 데이터에 담겨있어 결측값이 문제가 되지 않는 경우.
  • MAR(Missing At Random): 더 이해하기 쉬운 명칭은 Missing Conditionally at Random으로 결측조건이 다른 변수에 따라 조건부로 발생되는 경우. 결측값이 관측된 데이터가 아닌 관측되지 않는 데이터에 따라 결정.
    • 예를 들어, 남성이 여성보다 더 솔찍하게 나이, 몸무게 등을 밝힐 듯 싶다.
  • MNAR(Missing Not At Random): 결측값이 무작위가 아니라서 주도면밀한 추가 조사가 필요한 경우.
    • 예를 들어, 작업장에서 결측된 사람들 대부분은 아마도 몸이 아파 조사에서 결측되고, 교육수준이 낮은 사람이 교육조사에 결측될 듯 싶다.

데이터 생성과정을 이해하고 각 단계별로 왜 데이터에 누락이 발생했는지 따진다. 예를 들어, 미국 대선에서 왜 일부 유권자가 설문조사에 응답을 거부했는지 파악하고, 설문 항목에 문제가 없는지, 설문 문항에 불명확한 점이 있는지 다각도로 조사한다.

2 R에서 NA

결측값은 기록되어야만 하지만 기록되지 않는 값을 의미한다. NA**N**ot **A**vailable의 약자다. naniar 팩키지는 요인형 자료형 처리를 위해 개발된 forcats와 유사하게 NA 결측값 데이터 처리를 위해 개발된 팩키지로 자리잡고 있다.

2.1 결측값 파악

먼저 특정 벡터에 결측값이 있는지 여부는 any_na 함수로 파악하고, 해당 벡터의 원소가 결측값인지는 are_na 함수로 파악한다.

그리고 n_miss(), prop_miss() 함수로 결측갯수와 결측비율도 산출이 가능하다.

NA 파악

[1] TRUE
 [1] FALSE  TRUE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE

NA 갯수와 비율

[1] 5
[1] 0.5

2.2 결측값 연산

컴퓨터 과학에서 일반적으로 결측값(missing value)은 존재하지 않는 값(null)으로 컴퓨터에서 표현된다. 하지만 데이터 과학에서는 결측값이 무응답 혹은 단순히 자리만 차지하는 NA, \(\frac {0}{0}\)을 표현하는 NaN (Not a Number), 무한을 표현하는 inf가 있다.

R에 NA와 같이 미리 예약된 예약어가 몇개 있다. NaN, NULL, Inf가 대표적인다.

  • NULL: 값이 없다로 즉, 값이 존재하지 않는다는 의미로 사용
  • NaN: Not a Number로 \(\frac{0}{0}\)처럼 수학적으로 정의가 되지않는다는 의미.
  • Inf: Infinite의 약자로 무한대를 의미하는데, 수학적으로 \(\frac{10}{0}\)은 무한대가 된다.

NaN, NULL, Inf 각각이 결측값(NA)인지 살펴보자. any_na(NULL)은 TRUE로 결측값이 되고, 나머지는 결측값이 아니다. 결측값의 정의에서 기록되어야 하지만 기록되지 않은 값이 결측값이기 때문에 정의에 맞춰 잘 계산됨이 확인된다.

[1] TRUE
[1] FALSE
[1] FALSE

다음으로 R에서 특별히 정의된 예약어에 대해 연산을 수행하면 어떤 값이 되는지 확인해 보자.

NA에 TRUE/FALSE를 적용하면 TRUE/FALSE에 따라 값이 달라지고, NANaN를 연산하면 연산순서에 따라 결과가 달라진다.

[1] TRUE
[1] NA
[1] NA
[1] NaN

3 결측값 식별과 현황파악 4 5

결측데이터를 처리하기 전에 결측데이터를 처리하는 프로세스는 다음과 같다.

  1. 결측값을 식별한다. 원본데이터에서 다양한 형태로 결측정보가 표현되어 있으니 우선 현황 파악이 먼저다.
  2. 파악된 현황정보를 바탕으로 결측값을 컴퓨터가 처리가능한 형태로 부호화한다.
  3. 마지막으로 파악된 결측정보와 적절히 인코딩되어 컴퓨터에 저장된 결측값을 자료형에 맞춰 알고리즘을 적용하여 결측값을 처리한다.

결측값 대체 프로세스

3.1 결측데이터 생성

mlbench 보스톤 주택가격 데이터셋을 기본으로 결측값 관련 학습 내용에 대한 실습을 진행한다. 이를 위해서 연속형 변수 “ptratio”에 30개 NA 결측값을 주입하고, 범주형 변수 “rad”에 50개 NA 결측값를 주입한다.

3.2 결측값 현황 파악

결측값 현황 파악을 위해서 변수기준으로 결측값이 얼마나 되는지 파악하는 것과, 관측점 기준으로 얼마나 결측값이 발생되었는지 파악하는 두가지 경우가 있다.

먼저, apply 계열 함수를 사용해서 변수별, 관측점별 결측값이 얼마나 포함되어 있는지 파악한다. check_missing_value() 함수를 활용하여 변수별, 관측점별 결측값 백분율을 계산한다. 만약 5%이상 관측점 혹은 변수에 결측값이 포함되어 있으면 변수를 버리거나 혹은 관측점을 제거하는 전략을 택할 수도 있다.

다음으로 naniar 팩키지에 내장된 함수를 사용하는 방법이 있다.

  • 전반적인 결측값 현황 파악
    • n_miss()
    • n_complete()
  • 변수와 관측점별 결측값 파악
    • miss_var_summary()
    • miss_case_summary()
  • 변수와 관측점 교차표
    • miss_var_table()
    • miss_case_table()
  • 시계열
    • miss_var_span()
    • miss_var_run()

apply 계열함수 사용

    crim       zn    indus     chas      nox       rm      age      dis 
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
     rad      tax  ptratio        b    lstat     medv 
9.881423 0.000000 5.928854 0.000000 0.000000 0.000000 
       1        2        3        4        5        6        7        8 
0.000000 7.142857 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
       9       10       11       12       13       14       15       16 
0.000000 0.000000 0.000000 7.142857 0.000000 0.000000 7.142857 0.000000 
      17       18       19       20 
0.000000 0.000000 0.000000 0.000000 

naniar 팩키지 함수

[1] 80
[1] 7004
# A tibble: 14 x 3
   variable n_miss pct_miss
   <chr>     <int>    <dbl>
 1 rad          50     9.88
 2 ptratio      30     5.93
 3 crim          0     0   
 4 zn            0     0   
 5 indus         0     0   
 6 chas          0     0   
 7 nox           0     0   
 8 rm            0     0   
 9 age           0     0   
10 dis           0     0   
11 tax           0     0   
12 b             0     0   
13 lstat         0     0   
14 medv          0     0   
# A tibble: 506 x 3
    case n_miss pct_miss
   <int>  <int>    <dbl>
 1    93      2    14.3 
 2   486      2    14.3 
 3     2      1     7.14
 4    12      1     7.14
 5    15      1     7.14
 6    28      1     7.14
 7    33      1     7.14
 8    35      1     7.14
 9    44      1     7.14
10    58      1     7.14
# ... with 496 more rows

3.3 결측값 시각화

데이터프레임 행과 열에 걸쳐 분포되어 있는 결측값 현황을 새의 눈 관점(birds eye view)으로 살펴보자.

3.3.1 mice, VIM 팩키지

mice 팩키지를 사용해서 md.pattern 함수를 사용해서 “ptratio” 변수에 40개 주입한 NA 결측값을 확인해본다.

    crim zn indus chas nox rm age dis tax b lstat medv ptratio rad   
428    1  1     1    1   1  1   1   1   1 1     1    1       1   1  0
48     1  1     1    1   1  1   1   1   1 1     1    1       1   0  1
28     1  1     1    1   1  1   1   1   1 1     1    1       0   1  1
2      1  1     1    1   1  1   1   1   1 1     1    1       0   0  2
       0  0     0    0   0  0   0   0   0 0     0    0      30  50 80

혹은 VIM 팩키지를 활용하여 결측값을 시각화하는 것도 좋다. 결측값은 빨강색(red)로 설정하여 각변수별로 결측값에 대한 현황을 파악하기 쉽게 도식화했다.


 Variables sorted by number of missings: 
 Variable      Count
      rad 0.09881423
  ptratio 0.05928854
     crim 0.00000000
       zn 0.00000000
    indus 0.00000000
     chas 0.00000000
      nox 0.00000000
       rm 0.00000000
      age 0.00000000
      dis 0.00000000
      tax 0.00000000
        b 0.00000000
    lstat 0.00000000
     medv 0.00000000

marginplot(BostonHousing[, c('ptratio','medv')]) 그래프를 통해 변수 2개만 가능하지만, 결측값이 포함된 경우와 결측값이 없는 경우를 비교해 볼 수도 있다.

3.3.2 naniar 팩키지

naniar 팩키지 viz_miss() 함수로 데이터프레임 전체에 대한 시각화가 가능합니다. cluster=TRUE 선택옵션을 지정하면 전반적인 현황을 한눈에 파악할 수 있다.

naniar 팩키지 gg_miss_var(), gg_miss_case() 함수를 사용하면 변수별, 관측점별로 결측값에 대한 정보를 더 자세히 파악할 수 있다.

facet을 지정하여 범주형 변수 수준별로 결측변수별 결측값을 파악하는 것도 가능하다.

gg_miss_upset() 함수를 통해 변수와 관측점간 결측값도 동시에 시각화를 할 수 있다.