파이썬으로 배우는 포트폴리오 study day2

 

자주 사용 하는 통계량 (python code)

산술평균

nums = [1, 2, 3, 4, 5, 6]  # nums 리스트에 값을 저장
print( sum(nums) / len(nums)) # sum 함수로 합계를, len 함수로 데이터의 개수를 구한다.
# >> 3.5
import numpy as np  # numpy 라이브러리를 임포트
a = np.array([1, 2, 3, 4, 5, 6])  # array() 함수로 리스트를 array 객체로 저장
print(a.mean()) # 객체의 mean() 함수를 사용해 평균을 계산
# >> 3.5

 

기댓값

# 사건의 확률을 case와 prob 리스트에 저장
case = [1, 2, 3, 4, 5, 6]
prob = [1/6, 1/6, 1/6, 1/6, 1/6, 1/6]

# 사건과 확률 리스트를  zip 함수로 묶어 for 루프로 반복.
# 반복하는 동안 두 리스트에서 값을 받아 변수 c와 p에 저장하고 곱한 결과를 ex변수에 저장
ex = 0.0
for c, p in zip(case, prob):
    ex = ex + c*p

# ex = sum(c*p for c, p in zip(case,prob))
print(ex) # 결과를 출력
# >> 3.5

 

이동평균

  • 계산에 들어가는 값 중 가장 오래된 값을 버리고 새로운 값을 추가한 뒤 새로운 평균을 구함
  • 즉, 저지된 값이 아니라 새로운 데이터를 받아 그 대푯값을 업데이트함
# 이동평균
# 주가를 prices 리스트에 저장
prices = [44800, 44850, 44600, 43750, 44000, 43900, 44350, 45350, 45500, 45700]

# 5일 이동평균
n = 5

# prices의 n번째 항목부터 마지막 항목까지 반복
for p in prices[n:]:
    # 항목 p의 index를 마지막 인덱스로 정한다.
    end_index = prices.index(p)

    # 마지막 인덱스에서 n만큼 앞에 있는 시작 인덱스를 정한다.
    begin_index = end_index - n

    # end_index와 begin_index를 계산해 가져올 위치를 확인
    print(begin_index, end_index)

# 계산한 end_index와 begin_index를 갖고 prices 리스트에서 다섯 개 항목을 확인
for p in prices[n:]:
    end_index = prices.index(p)
    begin_index = end_index - n
    print(prices[begin_index : end_index])

# 다섯 개씩 가져와서 sum() 함수로 합계를 구하고 n으로 나눠 이동평균을 계산
for p in prices[n:]:
    end_index = prices.index(p)
    begin_index = end_index - n
    print(sum(prices[begin_index : end_index])/n)
0 5
1 6
2 7
3 8
4 9
[44800, 44850, 44600, 43750, 44000]
[44850, 44600, 43750, 44000, 43900]
[44600, 43750, 44000, 43900, 44350]
[43750, 44000, 43900, 44350, 45350]
[44000, 43900, 44350, 45350, 45500]
44400.0
44220.0
44120.0
44270.0
44620.0

 

가중 (산술) 평균

  • 자료의 중요도나 영향 정도에 해당하는 가중치를 고려해 구한 평균값
  • 주식의 평균매입단가
    • A종목 100주를 주당 5,000원 매입, 50주를 주당 7,500원에 추가 매수
    • 보유 수량은 150주이나 평균매입단가는 5,833.33원 (100 x 5000 + 50 x 7500) / (100 + 50)
  • WACC (Weighted Average Cost of Capital)
    • 회사의 자본 구조 중 부채와 지분의 시장가치를 바탕으로 한 가중평균이며 현금흐름을 할인하는 데 사용
# 평가 점수와 평가 비중을 scores와 weight 리스트에 저장
scores = [82, 90, 76]
weight = [0.2, 0.35, 0.45]

# scores와 weight 리스트를 zip 함수로 묶어 for 루프로 반복한다.
# wgt_avg는 합계를 저장할 변수
wgt_avg = 0

# 반복하는 동안 변수 s와 w에 저장하고 곱셈의 결과를 합함
for s, w in zip(scores, weight):
    wgt_avg = wgt_avg + s*w

# wgt_avg = sum(s*w for s,w in zip(scores, weight))
# 결과 출력
print(wgt_avg)
>> # 82.1

82x20% + 90x0.35% + 76x45% = 82.1

 

분산과 표준편차

$$
V = \frac{\sum |x-\bar{x}|^2}{n-1}
$$

$$
SD = \sqrt{\frac{\sum |x-\bar{x}|^2}{n-1}}
$$

# 분산을 계산할 리스트 nums를 준비
nums = [1, 2, 3, 4, 5]

# 리스트의 평균 계산
avg = sum(nums) / len(nums)

# 리스트를 반복해 편차 제곱합을 계산
sumsquare = 0

# nums 리스트를 반복하면서 n에 저장
for n in nums:
    # 여기서 평균(avg)을 뺀 결과를 제곱(**2)에 합계를 구한다.
    sumsquare += (n - avg)**2

# 위의 for 루프는 다음과 같이 바꿀 수 있다
sumsquare = sum((n - avg)**2 for n in nums)

# 편차 제곱합을 데이터 개수로 나누고 결과를 출력한다
var = sumsquare / (len(nums) - 1)
print(var)

# 표준편차를 구하려면 sqrt( ) 함수가 필요하므로 math 모듈을 임포트한다
import math
stdev = math.sqrt(var)
print(stdev)
# >> 2.5
# >> 1.5811388300841898

 

정규분포에서 표준편차와 평균

# numpy, matplotlib, scipy 라이브러리를 임포트
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

# x축은 -10 ~ 10 사이에서 0.001 간격으로 정한다.
x_axis = np.arange(-10, 10, 0.001)

# 평균 = 0, 표준편차 = 2.0 인 정규분포를 만든다.
plt.plot(x_axis, norm.pdf(x_axis, 0, 2))

# 정규분포 출력
plt.show()

 

 

자유도

  • 분산 또는 표준편차를 계산할 때는 데이터가 모집단(population)인지 또는 표본(sample)인지에 따라 계산이 달라짐
  • 모집단(population)인 경우, 분모는 N,
  • 분산 = 편차제곱합 / 데이터개수(N)
  • 표본(sample)인 경우, 분모는 N-1
  • 표본분산 = 편차 제곱합 / 표본 데이터의 개수(N-1)
    • N-1 : 표본집단의 분산 계산에 사용한 평균은 모집단의 평균이 아니므로, 오차를 일부 보정하기 위해 N-1 사용
    • 데이터가 표본집단에서 N-1로 편차 제곱합을 나눠야 모집단 분산에 대한 불편추정량(unbiased estimateor)가 되기 때문임
    • N-1을 자유도(degree of freedom)이라 함

 

 

공분산과 상관계수

 

$$
\sigma_{xy} = \frac{\sum(x-\mu_x)(y-\mu_y)}{n-1}
$$

  • $(x-\mu_x)(y-\mu_y)$를 보면 가로와 세로를 곱한 사각형의 면적의 모습
  • 합계를 개수(n-1)로 나눴다는 점에서 공분산 수식은 평균의 일종
  • 즉, 평균 $\mu$ 을 영점으로 하는 사각형 평균 면적

공분산에서 중요한 것은 부호

  • 공분산이 (+)이면 x, y는 양의 상관관계
  • 공분산이 (-)이면 x, y는 음의 상관관계
  • x와 y 변수 간의 방향성을 알려주지만 상관관계의 정도를 구체적으로 표현하지 못함

상관관계를 표준화한 값이 상관계수 (-1) ~ (+1)
$$
\rho_{xy} \equiv \frac{\rho_{xy}}{\rho_x \rho_y}
$$

$$
r = \frac{\sum XY - \frac{\sum X \sum Y}{n}}{\sqrt{\sum X^2 - \frac{(\sum X)^2}{n}}\sqrt{\sum Y^2 - \frac{(\sum Y)^2}{n}}}
$$

  • 상관계수 r값은 -1 ~ +1 사이 값인데 x=y이면 +1.0, 아주 다르면 0, 반대방향으로 완전 동일하면 -1
  • $r^2$은 x로부터 y를 예측할 수 있는 정도를 의미하며, 결정계수라고 한다.
  • 결정계수는 우리가 추정하는 선형 모델이 실제 데이터에 얼마나 잘 맞는지 알려주는 적합도를 나타내는 척도
# 상관계수를 계산하기 위해 필요한 함수들
import math

# 평균을 계산하는 함수
def mean( x ):
    return sum( x ) / len( x )

# 두 리스트 곱의 합계, 즉 엑셀의 SUMPRODUCT( ) 함수와 같다
def sum_of_product( xs, ys ):
    return sum( x * y for x, y in zip( xs, ys ) )

# 제곱합을 계산하는 함수
def sum_of_squares( v ):
    return sum_of_product( v, v )

# 편차를 계산하는 함수
def deviation( xs ):
    x_mean = mean( xs )
    return [ x - x_mean for x in xs ]

# 분산을 계산하는 함수
def variance( x ):
    n = len( x )
    deviations = deviation( x )
    return sum_of_squares( deviations ) / ( n-1 )

# 공분산을 계산하는 함수
def covariance( x, y ):
    n = len( x )
    return sum_of_product( deviation( x ), deviation( y ) ) / ( n-1 )

# 표준편차를 계산하는 함수
def standard_deviation( x ):
    return math.sqrt( variance( x ) ) # math 모듈의 제곱근 함수 sqrt( )를 사용

# 상관계수를 계산하는 함수
def correlation( xs, ys ):
    stdev_x = standard_deviation( xs )
    stdev_y = standard_deviation( ys )
    if stdev_x > 0 and stdev_y > 0:
        return covariance( xs, ys ) / ( stdev_x * stdev_y )
    else :
        return 0 # 편차가 존재하지 않는다면 상관관계는 0

# x와 y 리스트와 correlation( ) 함수를 사용해 상관관계를 계산
x=[ 41, 43, 38, 37 ]
y=[ 61, 63, 56, 55 ]
print( correlation( x, y ) )

x=[ 35, 45, 35, 34 ]
y=[ 65, 54, 64, 67 ]
print( correlation( x, y ) )

x=[ 35, 45, 35, 34 ]
y=[ 65, 66, 64, 68 ]
print( correlation( x, y ) )

# >> 0.9950765901904326
# >> -0.9910397700847882
# >> 0.009405128133399419
복사했습니다!