ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [4강] 데이터의 산포도 측정(분산, 표준편차, 범위 등)
    기초지식/Quantopian(강의노트) 2024. 11. 27. 22:02
    반응형

    산포도(Dispersion)는 데이터가 평균이나 중앙값 같은 중심값에서 얼마나 퍼져 있는지를 나타내는 값이다. 산포도는 범위(Range), 표준편차(Standard Deviation) 등으로 측정한다.

    범위(Range)

    numpy로 난수 생성하기

    데이터의 산포도 개념을 파악하기 위해서 분포를 가진 데이터를 먼저 만들어야 한다. 이 때 numpy 라이브러리를 이용하면, 손쉽게 난수 데이터를 만들 수 있다. 난수를 생성하기 위해서는 난수 생성기를 초기화 해주는 작업이 필요한데, numpy 의 random 클래스의 seed 함수를(np.random.seed()) 사용하면 된다. 이 때 seed()와 같이 괄호에 아무값도 안 넣으면 시스템 시간에 따라 seed값이 세팅된다. 시스템 시간은 계속 변화하므로 난수 생성 작업을 할 때마다 seed 값이 달라지고, 난수 시퀀스도 달라진다. 특정 seed 값을 np.random.seed(100)과 같이 넣어주면 난수 생성기는 고정된 상태로 초기화되므로 항상 동일한 난수 시퀀스를 얻을 수 있다.

    실제 난수를 생성하는 함수는 random, uniform, normal 등 다양하게 존재한다. 여기서는 정수를 생성하는 함수인 randint 함수를 사용하겠다. randint 함수는 np.random.randint(0,100,size=30)와 같이 사용할 수 있는데, 이는 0 보다 같거나 크고, 100 보다 작은(100 포함 X) 30 개의 난수를 생성한다는 의미이다. 마지막으로 생성된 난수를 np.sort를 통해서 정렬하는 내용까지 추가하면 아래와 같은 코드가 완성된다.

    import numpy as np
    
    np.random.seed(100)
    x = np.random.randint(0,100,size=30)
    x = np.sort(x)
    print(x)

    그림1: 난수 생성 예시

    범위 구하기

    범위(Range)는 최소값과 최대값의 차이이다. 간단한 척도 이지만 아래 그림 과 같이 이상치(Outliers)가 있으면 범위 값의 의미가 왜곡되는 단점이 있다. 아래 그림 1의 위에서 이상치가 없을 때 범위는 4 - 1 = 3 이지만 이상치인 10이 생기면 범위가 10 - 1 = 9로 급격하게 커지는 것을 확인할 수 있다.

    그림2: 이상치(Outliers)의 효과

    numpy 에서는 ptp 함수를 활용해서 range를 아래 코드로 구할 수 있는데, 위 그림1의 값의 range를 구한 값은 98 - 1 = 97 이 된다. 

    range = np.ptp(x)
    print(range)

    평균 절대 편차(MAD: Mean Absolute Deviation)

    평균 절대 편차를 구하기 위해서는 데이터의 평균값을 먼저 계산한다. 그리고 각 데이터 값과 평균의 차이를 구한 뒤 절대값을 씌워준다. 이렇게 계산한 값들의 평균을 구하면 평균 절대 편차가 된다. numpy 에서는 평균 절대 편차를 구해주는 라이브러리는 따로 없고, 아래와 같은 코드로 구현할 수 있다.

    # 평균값 계산
    mu = np.mean(x)
    # x 라는 배열의 각 값에서 평균을 빼고 절대값을 취한 것을 y 배열로 정의
    y = abs(x - mu)
    # y 배열의 평균 계산
    mad = np.sum(y)/len(y)
    print(mad)

    분산과 표준편차(Variance and Standard Deviation)

    평균 절대 편차, 분산, 표준편차 모두 데이터가 평균 주위에서 얼마나 퍼져 있는지를 나타내는 지표이다. 분산은 각 데이터들의 평균으로부터의 편차를 제곱한 값들의 평균이고, 표준편차는 분산의 제곱근이다. 분산은 제곱으로 이루어졌기 때문에 최적화 알고리즘을 적용할 수 있다. 다만 이 분산값은 관측값의 제곱 단위이기 때문에 직관적인 해석이 어렵다. 따라서 분산에 제곱근을 씌운 표준편차라는 개념을 이용해서 관측값과 단위를 맞춘 뒤 데이터를 해석한다.(최적화 알고리즘을 적용 못하는 "평균 절대 편차"보다 "분산과 표준편차"의 활용 빈도가 훨씬 높다.)

    분산은 각 데이터 값과 평균의 차이를 구한 뒤 제곱을 해준 배열을 정의해주고, 이 배열의 평균을 계산해서 구한다. 이렇게 구한 분산에 제곱근만(np.sqrt) 씌워주면 표준편차를 구할 수 있다. numpy에서는 var 이라는 함수를 통해서 분산을 구할 수 있고, std 라는 함수를 통해서 표준편차를 구할 수 있다.

    # x 라는 배열의 각 값에서 평균을 빼고 제곱을 한 것을 z 배열로 정의
    z = (x - mu)**2
    # z 배열 데이터의 평균 값 = 분산
    var1 = np.sum(z)/len(z)
    # numpy 의 var 함수를 통해서 분산 계산
    var2 = np.var(x)
    print(var1, var2)
    # var1에 제곱근을 씌워서 표준편차 계산
    std1 = np.sqrt(var1)
    # numpy 의 std 함수를 통해서 표준편차 계산
    std2 = np.std(x)
    print(std1, std2)

    반분산과 반편차(Semivariance and Semideviation)

    반분산과 반편차는 데이터의 하방리스크를 측정할 때 주로 사용된다. 데이터의 분산과 표준편차는 데이터의 변동성을 측정하지만 각 데이터가 평균보다 큰 경우와 작은 경우를 구분하지 않는다. 투자자 입장에서는 수익률의 평균 이하가 되는 경우가 더 중요하므로 반분산과 반편차는 투자 분석에서 의미가 있다.

    반분산의 계산은 데이터의(여기서는 위의 숫자배열 x) 각 값 중에서 평균보다 낮은 값으로만 이루어진 배열을 새롭게 정의하면서 시작한다. 그리고 각 데이터 값과 평균의 차이를 구한 뒤 제곱을 해준 배열을 정의해주고, 이 배열의 평균을 구하면 끝이다. 이렇게 계산한 값에 제곱근을 씌워주면 반편차가 나온다. 

    # x 라는 배열의 각 요소를 검토하여 평균보다 작은 값들만 모아서 lowers라는 배열 정의
    lowers = [i for i in x if i <= mu]
    # lowers 라는 배열의 각 값에서 평균을 빼고 제곱을 해준 배열을 y_lowers라고 정의
    y_lowers = (lowers - mu)**2
    # y_lowers 배열의 평균을 계산하여 반분산 계산
    semivar = np.sum(y_lowers)/len(y_lowers)
    # 계산한 반분산에 제곱근을 취해서 반편차를 계산
    semistd = np.sqrt(semivar)
    print(semivar, semistd)

    평균 대신에 target 값을 넣어서 반분산과 반편차를 계산할 수도 있다. 이렇게 계산한 값은 target 값에 대한 데이터의 하방리스크를 측정하는데 유용하게 사용될 수 있다.

    # target 값 48 임의로 설정
    target = 48
    # x 라는 배열의 각 항목을 검토하여 target보다 작은 값들만 모아서 lowers라는 배열 정의
    lowers = [i for i in x if i <= target]
    # lowers의 각 항목과 target 값과의 차이에 제곱을 한 값으로 구성된 z_lowers라는 배열 정의
    z_lowers = [(j - target)**2 for j in lowers]
    # z_lowers의 평균 계산하여 반분산 계산
    semivar = np.sum(z_lowers)/len(z_lowers)
    # 반분산에 제곱근을 취해서 반편차 계산
    semistd = np.sqrt(semivar)
    print(semivar, semistd)
    반응형
Designed by Tistory.