3-2. 결측값(결측치)

2019. 2. 14. 22:10

결측값(결측치) in R

  • NA(Not Available), 결측치라고 하며 값이 표기되지 않은 값.
  • R에서 [행,열] 중 행 인덱싱 자리에 is.na(dataframe) + sum(결측치 개수), mean(결측률) 을 얻을 수 있다. * pandas : df.isnull().sum() , mean()

결측값(결측치)의 종류

EDA를 하면서 결측치가 있는 칼럼을 + 시각화하여 Random(관깊칼럼X) / No random(관깊칼럼O-> 범주별 대치, 예측)을 판단해야한다.

  1. Random : 무작위로 정보가 없는 결측치, 다른변수별로 보면 결측비율도 달라진다. -> 삭제(전체or부분) or 조건부 대치 or 예측모형으로 해당변수 예측 모두가능
    ex> 몸무게 결측치, 남자<여자의 결측 가능성이 높다. -> 범주별 대치

  2. No random : 결측값 자체가 (민감한 정보라서) 패턴을 가짐 -> 관깊칼럼범주별 수치(평균/중앙값/최빈값)으로 대치
    ex> 고소득자와 저소득자의 연봉은 결측치가 될 확률이 높다 -> 관계 깊은 칼럼인 사는곳별 평균/중앙값/최빈값 or예측값으로 대치

결측치를 탐색하는 방법 2가지 (표+시각화)

  1. : mice패키지 -> 결측치 1(아닌 것을 0)으로 표기한 뒤 x 갯수로 나타내어 조합별로도 확인가능
  2. 시각화
    1) cor(y) : 결측치 1(아닌 것을 0)에 대해 이변수간의 상관관계로서 결측치를 나타낸다.
    2) Vim패키지 : 결측치(빨간색)의 빈도 및 패턴을 시각화한다. 결측된 양을 scalebar로 나타내준다.

결측치 처리방법 3가지

  1. 삭제
    1) List Wise Deletion : row가 어느 한 칼럼(변수)라도 missing이면 삭제 -> 간단하지만, sample size가 떨어져 power가 낮아진다.
    2) Pair Wise Deletion : 관심있는 칼럼(변수)에 값이 있다면, 포함시킨다.

  2. 대치(Imputation)
    1) 최빈값(mode, qualitative) : 범주형에서 결측값이 발생시, 범주별 빈도가 가장 높은 값으로 대치한다. -> but bias가 많이 발생할 수 있다. ex> 남자, 여자 중에 남자의 빈도가 높다고 남자도 대치한다면, bias가 높아진다.
    2) 중앙값(median) : 숫자형(연속형)에서 결측값제외한 중앙값으로 대치방법
    3) 평균(mean) : 숫자형(연속형)에서 결측값제외한 평균으로 대치방법
    4) Similar case imputation : 조건부 대치
    5) Generalized Imputation : 회귀분석을 이용한 대치

  3. 예측모델(Prediction model)
    1) 결측값이 없는 칼럼(변수)들로 구성된 dataset으로 -> 결측값이 있는 칼럼을 예측하게 한다.
    2) 예측값으로 해당칼럼을 채워넣는다.


  4. 가장 흔히 쓰는 방법
    1) 하나라도 결측이 있는 변수 제외한 dataset생성
    2) imputation한 dataset 2개 정도 생성 (mean or median / regression / KNN 등으로)
    3) 1)과 2)의 dataset 3개에 대해서 결과값이 서로 일관성 있음을 보여준다. -> 결측대치방법이 senvitivity하지 않다는 것을 제시하는 것

결측값(결측치) 처리 가이드라인

  • 10% 미만: 삭제 or 대치
  • 10 ~ 20% : Hot deck(매년자료->해당년자료 추정) or regression or model based imputation
  • 20 ~ 50% 이상 : regression or model based imputation
  • 50% 이상 : 해당 칼럼(변수)자체 제거

결측값 삭제 or 대치의 한계점

  1. 삭제를 통해 n수가 달라진다 -> 집단의 특성이 달라질 수 있다. -> missing rate(10%미만)을 확인하고 삭제한다

  2. 대치는 틀린값으로 대체될 수 있다는 가능성이 항상 존재한다

3-1. 이상치

2019. 2. 14. 21:34

이상치(Outlier)에 대해

  • 이상치 처리는 데이터 분석 중 가장 많은 시간이 소요된다.
  • EDA & data cleaning, data preprocessing, data manupulation, data massage, data munging, data wrangling

이상치

  1. 정의 : 데이터 전체적인 패턴에서 동떨어져있는 관측 값

    • 영향점이라고도 불림.
    • 독립변수(x축)에 있는 이상치(영향점) : 지대점
    • 종속변수(y축)에 있는 이상치(영향점) : 아웃라이어
    • boxplot에서 가운데 box의 높이 : 3Q - 1Q = IQR, 가운데 50%를 의미
    • boxplot에서 box양쪽 막대 : 3Q + 1.5*IQR = Upper fence, 1Q-1.5*IQR = Lower fence
    • boxplot에서 Upper, Lower fence 보다 바깥에 있는 값 : 아웃라이어
  2. 단변수(boxplot)에서 안보이던 이상치(Outlier)가 이변수(산점도)에서 보일 수 있다.

    • 반드시 그림으로 그려봐야한다.
    • EDA를 통해 새로운 이상치를 발견할 수 있다.
  1. 종류 :
    1) 실수에 의한 아웃라이어 : 수집시 오류 + 측정단위 오류 + 실험시 에러
    2) 자연(real연구대상)적 발생 아웃라이어 : 직원들월급 중 임원들은 따로 빼서 분석해야함. 자연적으로는 너무 차이날 수 밖에 없음.
    3) 역코딩에 의한 아웃라이어 : 설문지에 의도적으로 1번과 5번 성향을 바꿔놨는데, 데이터 분석시 고려안함
    4) 의도적 아웃라이어 : 설문조사시 10대들은 알콜섭취량 일부러 낮게 적음
    5) sampling 아웃라이어 : 표본 중에 우연히 이상치요소들이 포함 ex> 사람들 키 조사하는데 농구선수도 포함됨
  1. 이상치(아웃라이어)의 영향력

    • 평균뿐만 아니라 분산(표준편차)가 엄청 커져 -> 엄청 불안정한 자료가 된다.
    • 중앙값(median)은 그나마 영향을 덜 받는다.

이상치 발견의 방법

  1. 시각화 : 단변수 boxplot -> 이변수 scatter plot
  2. Z(표준정규)분포상 3sd이상 떨어진 값들 : 3sd는 왼쪽 2.5%이하, 오른쪽 97.5%이상
    • 1sd사이 : 68.27%
    • 2sd사이 : 95.45%
    • 3sd사이 : 99.73%
  3. 도메인 knowledge를 특정기준으로 두고 파악 : ex 수축기 혈압 120 ~ 160 벗어나는 값들

이상치 제거 방법

  1. 삭제 : 입력시 error거나 outlier수가 굉장히 적을 경우는 그냥 삭제
  2. 대치(Imputation) : 다른 값으로 변경
    • 범주별 mean/median/mode 등으로 대치
    • 통계적모델링(종속변수로 취급하여, 다른변수들로 예측 후 대치)
    • Binning(숫자의 분포를 범주로 매핑)
  3. 스케일링(scaling) : 보통 right skewed(캐글에서 0.75이상)인 경우 logsquare root(제곱근)을 취한다
  4. 정규화(normalization) : MinMax, Z-score 등으로 정규화시킨다.

sql고수 효* 선생님께 sql을 다룰 수 있는 간단한 설명과 자료를 건네주셨다.
의료데이터이므로 민감한 자료라 보관을 잘하고 연습후 폐기를 잘해야할 것이다.
나는 이것을 sql로 EDA를 마치고 python으로 불러와서 EDA 및 feature engineering을 거친 뒤, 머신러닝 알고리즘으로 예측해보려는 시도를 해보겠다

보고서 작성이 금요일까진데,, 월요일부터 본격 시도를 하려고한다..
ㅠㅠ 시간이 많이 촉박하다..

통계적 추론 2가지

어떤 이론이 과학적이려면 반증 가능성을 가져야한다.
반증가능성이란? 가설이 실험or관찰에 의해서 반증될 가능성
쉽게 말하자면, H1을 증명하기 어려우니 H0가 아니다로 증명

통계적 추론
1.추정 : 표본으로 모수 등 모집단에 대한 어떤 값을 추즉하는 과정으로 추정값 + 오차범위(표본오차, 신뢰구간) 같이 제시
- 추정 : 모집단의 평균이 30이다.

2.가설검정 : 표본으로 모집단에 대한 주장or가설의 옳고 그름을 판정 하거나 대립가설(H1)을 채택 or 귀무가설(H0)을 기각
- 검정 : 모집단의 평균이 30보다 클 것이다.

가설검정의 4가지 절차

1.알고있던 귀무가설(H0)입증하고자하는 대립가설(H1) 세우기 - 보수적, 잘 알려진 것을 H0로 잡고, H0를 실험한다.
- 입증하고자하는 대립가설을 증명하기는 너무 어려우니 알고 있던 귀무가설이 참이라고 가정하고 실험해서 반증하자
- 반증의 기준은 알고 있던 H0의 결과(검정통계량)가 연구자가 정한 유의수준(H0실험 분포상 x축에 찍히는 임계치결정)보다 바깥쪽에 찍혀 검정통계량(H0의 결과)에 의한 유의 확률이 기각역에 포함되어 **우연에 의한것으로 판단** -> 입증하고자**하는 H1가 유의미하다는 것으로 반증**.

2.검정통계량산출(H0가 참이라고 가정하고 한 실험에서 나온 결과 - 해당 분포 그래프 상 x축에 찍히는 점)

3.유의수준 결정 by 연구자 ( 분포상 임계치(-x축에 찍히는 점)와 기각역(-임계치보다 바깥쪽)을 결정)
- 유의수준은 연구자가 결정하는 것으로 H0로 실험한 결과를 우연이 아니라고 해줄 수 있는 한계치. 보통 p-value : 0.05로 한다.
- 유의확률은 H0로 실험한 결과 나오는 확률이다.

4.검정결과 해석

가설검정에 대하여

가설검정 자체는 보수적인 실험으로서 반증가능성을 실험한다.
먼저, 알고 있던 귀무가설(H0)는 실험전까지 맞고 판단하면서 살아간다.
다음, 입증하고자 하는 대립가설(H1)은 실험 후, 알고있던 귀무가설이 아니라는 충분한 근거(유의확률이 유의수준보다 적게나왔을 때)가 있을 때 채택한다.

통계적 추론(값 추정과 가설 검정)의 목적은 data로 의사결정을 내리는 것이다.
통계적 추론(값 추정과 가설 검정)에서의 통계적(statistical)이라는 말은 표본을 이용해서 추론한다는 말이다.

통계라는 말에는 항상 에러가 우연히 발생(error)가 있으니, 우연이 아니라 정말 의미가 있다(effect)를 근거로 통계 분석(통계적 추론 중 가설검정)을 통해 시작한다.

즉, 실험 결과가 우연(error)냐 아니냐(effect)를 결정하는 것이 가설검정이다.

가설검정의 용어

  1. H0 : 알고 있던, 기존에 알려진 가설 = 귀무가설 => 유의확률(p-value) - (x축상 검정통계량, H0의 결과확률)가 유의수준(0.05)(x축상 임계치)보다 작을 때 기각
    -이것을 바탕으로 표본을 이용해 실험이 이루어진다. 분포, 그래프 전부다H0가 참이다라는 가정하에 그려진다.
  2. H1 : 입증하고자 하는, 알고자하는 가설 = 대립가설 => 유의확률(p-value)가 유의수준(0.05)보다 작을 때 채택
    연구자는 귀무가설을 기각하고 싶어하고, 대립가설을 채택하고 싶어 할 것이다.
  3. 제 1종 오류(a) : 귀무가설이 참인데 불구하고, 귀무가설을 기각 = 대립가설을 채택한 오류 => 제 2종 오류보다 심각 => 허용한계를 정해야함(보통 0.05)
    -효과/차이가 없다(H0)가 참인데 불구하고 기각 + 효과/차이가 있다고 판단. => 엄청난 부작용 발생가능성
  4. 유의 확률(p값,p-value, significance probability) : 제 1종 오류가 발생할 확률 = 귀무가설이 참인데 불구하고 알고자하는 대립가설을 채택할 확률 -> 이것의 허용치가 유의수준 -> 유의수준 허용치 안에 들어온다면, H0(귀무가설)기각 H1(대립가설 채택).
  5. 유의수준(Significant Level) : <귀무가설이 참이다 가정 하에> 데이터를 기반으로한(표본을 이용한) 실험결과(검정통계량)가 항상 옳은 것이 아니므로 연구가가 정한 유의확률(제1종오류가 발생할 확률 = 귀무가설이 참인데, 기각 + 대립가설을 채택하는 확률)의 최대허용한계, 최대값, 마지노선. 보통은 0.05로 잡는게 관례 => 실험의 분포 x축에 임계치(Critical value)가 결정되며, 그 이하가 H0의 기각역(Critical Region or reject region)이 됨
    -쉽게 말하면, 유의수준 0.05 = 100번 중 최대 5번까지는 실수(제1종오류=귀무가설 참인데 기각)가 발생하더라도 허용한다.
    -유의확률 0.03 = 100번 중 3번 실수(H1를 채택) -> 100번 중 5번(유의수준 0.05) 안에 들었다. -> 귀무가설이 참이더라도 기각하고 대립가설 채택
  6. 제 2종 오류(b) : 귀무가설이 거짓인데 불구하고, 귀무가설을 기각하지 않은 오류 = 제 2종 오류(b)
  7. 검정통계량(Test Statistic, M-) : 귀무가설이 참이다는 가정 하에, 표본을 이용하여 계산된 통계량, 실제 실험의 결과 => 검정 통계량 이하의 확률이 유의확률이 됨

가설검정의 예시

  1. H0 : A반 키의 평균은 160이다.에 대해 H1 : A반 키의 평균은 160이 아니다를 입증하고 싶다.
    1) 가설설정은 되었다. 2번째 검정통계량(H0 참이라는 가정하 실험해서 결과)을 구하기 위해, A반 학생 10명을 뽑아서 평균 키를 젠다
    2) 유의수준(0.05)하에서 검정통계량(10명의 평균 키)을 바탕으로 유의확률을 계산한다
    3) 기각역에 들어오면 H0 기각 = H1 채택한다.

  2. 휴지가 300m인지 확인해보고싶다. (보수적, 잘알려진 H0 : 휴지의 평균길이는 300m임)
    1) 가설설정 : H0 : 휴지의 평균길이 300m이다. H1 : 휴지의 평균길이가 300m이 아니다.
    2) H0하에 검정통계량을 계산하기 위해서 휴지 10개의 길이를 제고 유의수준하에 유의확률을 확인한다
    3) H0기각 = H1채택 하거나 H0를 그대로 기각하지않는다.

  3. 숟가락이 잘 구부려진다 -> 나는 초능력자다( 보수적, 잘알려진 H0 : 나는 초능력자x : 내 능력 = 다른사람의 능력)
    1) 가설설정 : H0 : 나의 능력 = 다른사람들의 능력(보통 숟가락30개 구부림) / H1 : 내 능력 != 다른사람들의 능력(30개보다 더 많이 구부릴 것이다)
    2) H0하에서 10명과 함께 숟가락 구부린 횟수의 평균과 내 구부린 횟수의 평균을 비교하여, 검정통계량을 계산한다
    3) 유의수준하에서 유의확률을 확인하여, H0 기각 ? 기각x ? 를 결정한다.

  4. 듀라셀 vs 에너자이져의 수명 차이
    1) 가설설정 : H0 : 듀라셀 수명 = 에너자이저 수명
    2) H0하에서 10개의 평균 수명을 비교 실험하여 검정통계량 계산
    3) 유의수준 하(H0실험의 t분포에서 0.05)에서 검정통계량에 의한 유의확률을 확인하여 H0 기각x or H1 채택 을 선택한다.

가설검정의 종류

  1. 양측검정 : H1 : Ma != Mb 으로서 실험결과분포의 양쪽(Ma > Mb & Ma < Mb)을 봐야한다.
  2. 단측검정 : H1 : Ma > Mb or Ma < Mb으로서 실험결과분포의 한쪽만 본다.

오늘날의 p-value

  1. 빅데이터 시대로서 n수가 늘어나서 -> 유의확률0.05 들어가는 검정통계량도 늘었다 -> 다 유의하다고 나옴
  2. p-value만 보기에는 문제가 생길 수 있다. -> 평균차이와 비율차이를 같이 제시
  3. 유의함을 넘어서 더 좁아진 유용함(MCID, The Minimal Clinically Important Change Score)구간도 생김
  4. JAMA에서 발표한 임상의 확증적 연구 : 0.005쓰자
  5. 미국통계학회(ASA) : 종합해서 판단하자.

문자열로 입력된 날짜를 임시로 만들고 년/월/일을 짤라놓은 뒤 || 을 이용해 년 월 일을 '-'로 연결한 뒤,다시 DATE타입으로 바꾸어 연산해보는 공부

  • 칼럼을 생성하고 싶다면 : SELECT절에서  값 AS 칼럼명
  • timestamp 1개로 년/월/일 3개로 나누기 : TOCHAR_( date or timestamp, ' date 기호 ')
  • || : SELECT절에서 문자열칼럼 or 생성한문자열 을 concat해준다.
  • 둘다 DATE타입일 경우, 마이너스 연산이 가능하다. 연산결과는 n days + 시간 -> int로 캐스팅해야 숫자로 사용( 나누기 365 등)할 수 있다.
  • PosgreSQL에서 birthday를 만나이로 계산하는 순서(년/월/일)로 나뉘어있다고 가정
    (1) || 을 통해 YYYY-MM-DD형태로 변환
    (2) DATE타입으로 캐스팅
    (3) NOW()현재날짜와 (-) 연산
    (4) int타입으로 캐스팅
    (5) /365해주기

  • MSSQL에서 birthday를 만나이로 계산하는 순서( YYYY-MM-DD)로 나뉘었다고 가정 :
    (1) DATEDIFF( day, 시작날짜, GETDATE()) / 365자동연산


전처리

  1. 기존 테이블
  1. SELECT에 < 한개의자료 AS 칼럼명 > 으로 새 칼럼을 생성한 뒤, INTO로 테이블 생성

    • '문자열' AS 칼럼명 (text형으로 칼럼생성)
    • NOW() AS 칼럼명 (timestamp형로 칼럼생성) 등등.. 다된다.
      SELECT *, NOW() AS time INTO students_with_birthday FROM students;
      
  2. time칼럼에 날짜 입력해주기

    UPDATE students_with_birthday SET time = '1987-01-30' WHERE name ='Moe';
    UPDATE students_with_birthday SET time = '1988-03-29' WHERE name ='Larry';
    UPDATE students_with_birthday SET time = '1980-02-28' WHERE name ='Rolf';
    UPDATE students_with_birthday SET time = '1987-06-27' WHERE name ='Anne';
    UPDATE students_with_birthday SET time = '1991-02-26' WHERE name ='Robert';
    UPDATE students_with_birthday SET time = '1958-01-26' WHERE name ='Jose';
    

  1. 날짜(YYYY-MM-DD)를 문자열 & 년/월/일 로 분리하여 칼럼 만들고, 확인되면 INTO 넣어서 필요한 칼럼들만으로 테이블로 만들기
    SELECT *,
     TO_CHAR(time, 'YYYY') as year_of_birth, 
     TO_CHAR(time, 'MM') as month_of_birth, 
     TO_CHAR(time, 'DD') as day_of_birth 
    FROM students_with_birthday
    
    SELECT name, current_mood,
     TO_CHAR(time, 'YYYY') as year_of_birth, 
     TO_CHAR(time, 'MM') as month_of_birth, 
     TO_CHAR(time, 'DD') as day_of_birth 
    INTO students_birthday
    FROM students_with_birthday
    SELECT * FROM students_birthday
    

문자열인 년/월/일 칼럼을 || 과 sep '-'로 붙히는 연습해보기

  1. 문자열칼럼 || '문자열' or 문자열 칼럼
    SELECT year_of_birth  FROM students_birthday                         -- 2019
    SELECT year_of_birth||'-'  FROM students_birthday                     -- 2019-
    SELECT year_of_birth||'-'||month_of_birth  FROM students_birthday            -- 2019-02 
    SELECT year_of_birth||'-'||month_of_birth||'-'||day_of_birth FROM students_birthday     -- 2019-02-01
    
  1. 문자열 YYYY || MM || DD 를 concat(||)으로 붙힌 것을 CAST( AS DATE)으로 타입 변환하기 ( YYYY-MM-DD 형태 아니면 안됨 )

    SELECT CAST( year_of_birth||'-'||month_of_birth||'-'||day_of_birth AS DATE),* FROM students_birthday 
    
  2. date타입으로 바꿨으면, 특정시간칼럼과 연산이 가능하다.

    SELECT NOW() - CAST( year_of_birth||'-'||month_of_birth||'-'||day_of_birth AS DATE) FROM students_birthday 
    

  3. 날짜(둘다 DATE여야함.) 차이결과는 days +시간으로 나온다. 이것을 int로 다시 형변환하면, day숫자만 나온다. * NOW()는 date가 아니라 timestamp로서 다른 타입이니 또 캐스팅

    SELECT CAST( CAST(NOW() AS DATE) - CAST( year_of_birth||'-'||month_of_birth||'-'||day_of_birth AS DATE)  AS INT) FROM students_birthday 
    
  4. day를 /365 로 나누면, 만나이(년수)가 나온다.

    SELECT CAST( CAST(NOW() AS DATE) - CAST( year_of_birth||'-'||month_of_birth||'-'||day_of_birth AS DATE)  AS INT) / 365 FROM students_birthday 
    


+ Recent posts