1. 통계 기초
01. 모집단과 표본모집단(Population): 연구 대상 전체를 의미하며, 모든 데이터를 포함한다.
-
- ex) 특정 나라의 모든 사람의 키 데이터
- 표본(Sample): 모집단의 일부를 추출한 데이터를 의미하며, 모집단의 특성을 추정하는 데 사용된다.
02. 기술통계와 추론통계
- 기술통계 : 데이터를 요약하고 설명하는 데 사용되는 통계 기법이다. 평균, 중앙값, 최빈값, 표준편차 등이 포함
- 추론통계 : 표본 데이터를 사용하여 모집단에 대한 추론을 수행하는 통계 기법이다. 가설 검정, 신뢰 구간 등이 포함
03. 이산값과 연속값
- 이산값
- 특정한 값을 가지는 데이터로, 정해진 간격이나 구간 안에서만 나타난다
- 값들이 셀 수 있는 숫자처럼 구분되어 있어 중간값이 없다
- ex) 주사위 눈(1, 2, 3, 4, 5, 6), 사람 수(1명, 2명, 3명 등)
- 데이터의 값은 유한하거나 명확하게 구분될 수 있다.
- 연속값
- 측정할 수 있는 모든 값을 포함하는 데이터로, 구간 내의 어떠한 값도 가능하다.
- 무한한 소수점 단위까지 값을 가질 수 있어, 값 사이에 중간값이 존재할 수 있다
- ex )몸무게(55.5kg, 60.7kg 등), 온도(20.3°C, 21.8°C 등)
- 데이터의 값은 연속적이어서 값들 간의 경계가 모호하다
04. 중심 경향 측도
# 평균
arr = np.array([10, 20, 30, 40])
print(np.mean(arr)) # 25.0
# 중앙값
print(np.median(arr)) # 25.0
# 최빈값
from scipy import stats #. NumPy에는 내장 함수가 없지만, scipy.stats 패키지를 이용해 계산할 수 있다.
arr = np.array([10, 20, 20, 30, 40])
print(stats.mode(arr)) # Mode: 20
🤔 그렇다면, 우리반의 평균 키와 최빈값을 구해보자!
height = np.array([160, 170, 180, 150, 150, 155, 165, 175, 185, 180, 175, 170, 173, 164, 189, 175])
# 평균값
print(np.mean(height))
# 정렬
print(np.sort(height))
# 중앙값
print(np.median(height))
# 최빈값 --> 중복값을 제외하고 고유한 값 / 그 갯수
values, count = np.unique(height, return_counts = True)
print(values,count)
# 최빈값
most = np.max(count)
print(most == count) # boolean으로 해당값의 True, False 여부를 확인해줌
print(values[count == most])
[출력]
169.75
[150 150 155 160 164 165 170 170 173 175 175 175 180 180 185 189]
171.5
[150 155 160 164 165 170 173 175 180 185 189] [2 1 1 1 1 2 1 3 2 1 1]
[False False False False False False False True False False False]
[175]
05. 산포 측도
# 분산 : 데이터가 평균으로부터 얼마나 떨어져있는지 / 클수록 퍼져있음
print(np.var(arr)) # 125.0
# 표준편차 : 분산의 제곱근
print(np.std(arr)) # 11.1803
# 범위 : 데이터의 최댓값과 최솟값의 차이
print(np.max(arr) - np.min(arr)) # 30
06. 확률과 확률분포
- 확률 : 특정 사건이 발생할 가능성을 0과 1의 사이의 값으로 나타낸다. 1에 가까울수록 가능성이 크다
- 확률분포 : 확률 변수가 가질 수 있는 값과 그 값이 나올 확률을 나타내는 함수
- ex) 각 경우가 나올 확률이 균등한 균등분포 (주사위)
07. 정규분포와 균등분포
- 정규분포 : 평균을 중심으로 데이터가 대칭적으로 분포하며, 종 모양의 분포를 나타낸다. 정규분포에서는 평균 근처의 값이 자주 나타나고, 양 끝으로 갈수록 빈도가 감소한다.
arr = np.random.randn(1000) # 평균 0, 표준편차 1인 정규분포 난수 1000개
print(np.mean(arr), np.std(arr))
[ 68-95-99.7 규칙 ]
정규 분포를 나타내는 규칙으로, 경험적인 규칙(empirical rule)이라고도 한다.
3시그마 규칙(three-sigma rule)이라고도 하는데 이 때는 평균에서 양쪽으로 3표준편차의 범위에 거의 모든 값들(99.7%)이 들어간다는 것을 나타낸다.
- 약 68%의 값들이 평균에서 양쪽으로 1 표준편차 범위 '1시그마' 에 존재한다.
- 약 95%의 값들이 평균에서 양쪽으로 2 표준편차 범위 '2시그마' 에 존재한다.
- 거의 모든 값들(실제로는 99.7%)이 평균에서 양쪽으로 3표준편차 범위 '3시그마' 에 존재한다.
- 균등분포 : 모든 값이 동일한 확률로 발생하는 분포를 의미한다.
- 0.0 이상 ~ 1.0 미만 수에서 균등하게 난수 추출
- np.random.randint(start, end, size) => start 이상 end 미만의 난수를 size 만큼 추출
arr = np.random.uniform(0, 1, 1000) # 0과 1 사이의 균등분포 난수 1000개
print(np.mean(arr), np.std(arr))
2. ndarray 정렬
01. 기본 배열 정렬
1차원 배열 정렬
arr = np.random.randint(1, 11, 10)
print(arr)
[출력]
[10 1 2 1 4 4 10 2 2 2]
# np.sort(arr) : 정렬된 ndarray를 반환
print(np.sort(arr))
print(np.sort(arr)[::-1]) # 내림차순 정렬
print(arr)
[출력]
[2 2 3 3 4 6 8 9 9 9]
[9 9 9 8 6 4 3 3 2 2]
[4 3 9 9 2 6 8 2 3 9]
-1 인덱싱을 사용하여 내림차순 정렬도 가능하다
2차원 배열 정렬
arr = np.random.randint(10, size=(3, 4)) # 0 이상 10 미만
print(arr)
[출력]
[[1 5 7 9]
[8 9 2 8]
[8 6 4 7]]
02. 특정 축을 기준으로 정렬
print(np.sort(arr, axis=0)) # 행 방향 정렬 (같은 열 안에서 정렬)
print(np.sort(arr, axis=1)) # 열 방향 정렬 (같은 행 안에서 정렬) ⭐기본값
print(np.sort(arr, axis=None).shape) # axis = None 축 무시 (행/열 구분없이 모든 값 정렬)
[출력]
[[1 5 2 7]
[8 6 4 8]
[8 9 7 9]]
[[1 5 7 9]
[2 8 8 9]
[4 6 7 8]]
(12,)
(12,)
03. 인덱스를 반환하는 정렬
💡np.argsort
- 배열의 값을 정렬했을 때, 각 값의 원래 인덱스를 반환
- 정렬할 때 어떤 순서로 값을 배치해야 하는지 알려주는 인덱스를 반환
- 배열의 값을 정렬한 후, 정렬된 순서에 해당하는 인덱스를 반환
(1) 1차원 배열에서 argsort 사용
names = np.array(['리사','로제','제니','지수'])
album_sales = np.array([900, 870, 1000, 670])
result = np.argsort(album_sales)
print(names[result][::-1])
[출력]
['제니' '리사' '로제' '지수']
(2) 2차원 배열에서 argsort 사용
# 2차원 배열에서 argsort
arr = np.array([[2025, 2, 28],[17, 18, 30]])
print(arr)
print(np.argsort(arr))
print(np.argsort(arr, axis=1)) # 열 방향 정렬의 순서 (같은 행 안에서 정렬)
print(np.argsort(arr, axis=0)) # 행 방향 정렬의 순서 (같은 열 안에서 정렬)
[출력]
[[2025 2 28]
[ 17 18 30]]
[[1 2 0]
[0 1 2]]
[[1 2 0]
[0 1 2]]
[[1 0 0]
[0 1 1]]
3. ndarray 병합
01. 배열 병합이란
배열 병합은 여러 개의 배열을 연결하여 하나의 배열로 만드는 방법이다. NumPy에서 배열을 병합하는 방법은
np.concatenate(), np.vstack(), np.hstack() 등의 함수를 사용한다.
02. np.append()
arr1 = np.arange(1, 13).reshape(3,4)
arr2 = np.arange(13, 25).reshape(3,4)
arr1, arr2
[출력]
(array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]]))
print(np.append(arr1,arr2))
print(np.append(arr1, arr2, axis=0)) # 행 기준 병합
print(np.append(arr1, arr2, axis=1)) # 열 기준 병합
[출력]
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]
[[ 1 2 3 4 13 14 15 16]
[ 5 6 7 8 17 18 19 20]
[ 9 10 11 12 21 22 23 24]]
03. 수직 수평 배열병합
- vstack, hstack에서 병합 대상은 튜플 또는 리스트 형태로 묶어줘야 한다
(1) np.vstack
- axis = 0 병합과 같다
print(np.vstack((arr1, arr2)))
(2) np.hstack
- axis = 1 병합과 같다
print(np.hstack([arr1, arr2]))
4. ndarray 분할
01. np.split()
print(np.split(arr, 2)) # 원본배열, 분할할 갯수, axis
print(np.split(arr, 2, axis=0))
print(np.split(arr, 2, axis=1))
[출력]
[array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]]), array([[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]])]
[array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]]), array([[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]])]
[array([[ 1, 2],
[ 5, 6],
[ 9, 10],
[13, 14],
[17, 18],
[21, 22]]), array([[ 3, 4],
[ 7, 8],
[11, 12],
[15, 16],
[19, 20],
[23, 24]])]
5. ndarray 형태변경
01. 1차원 => 2차원 형태 변경
arr = np.arange(12)
print(arr.ndim, arr)
[출력]
1 [ 0 1 2 3 4 5 6 7 8 9 10 11]
arr = arr.reshape(3, 4)
# arr = arr.reshape(2, 7) # error !!! 2행 7열을 만들기 위한 요소가 부족하다
print(arr.ndim, arr.shape)
print(arr)
[출력]
2 (3, 4)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
02. 2차원 => 다차원 형태 변경
arr = arr.reshape(2,2,3)
# arr = arr.reshape(2,2,2) 얘는 안돼요!!
print(arr.ndim, arr.shape)
print(arr)
[출력]
3 (2, 2, 3)
[[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]]
03. 다차원 => 1차원
reshape(-1)
# reshape() -> -1
arr = arr.reshape(-1)
print(arr)
[출력]
[ 0 1 2 3 4 5 6 7 8 9 10 11]
arr = arr.reshape(4, -1)
print(arr)
[출력]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
arr = arr.reshape(-1, 4)
print(arr)
[출력]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
np.ravel()
arr1 = np.arange(50).reshape(5,10)
print(arr)
print(np.ravel(arr))
[출력]
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
48 49]
04. 차원 확장
np.expand_dims
- 요소의 변화는 없지만, 차원의 수를 늘려 shape을 구성한다
# 1차원 -> 2차원
arr2 = np.arange(10)
print(arr2.shape, arr2)
print(np.expand_dims(arr2, axis=0))
print(np.expand_dims(arr2, axis=0).shape)
print(np.expand_dims(arr2, axis=1))
print(np.expand_dims(arr2, axis=1).shape)
[출력]
(10,) [0 1 2 3 4 5 6 7 8 9]
[[0 1 2 3 4 5 6 7 8 9]]
(1, 10)
[[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]]
(10, 1)
# 2차원 => 3차원
arr3 = np.array([[1, 2],[3, 4]])
print(arr2.shape, arr2)
print(np.expand_dims(arr3, axis=0))
print(np.expand_dims(arr3, axis=0).shape) # 0번 인덱스에 차원 추가
print(np.expand_dims(arr3, axis=1))
print(np.expand_dims(arr3, axis=1).shape) # 1번 인덱스에 차원 추가
print(np.expand_dims(arr3, axis=2))
print(np.expand_dims(arr3, axis=2).shape)
[출력]
(2, 2) [[1 2]
[3 4]]
[[[1 2]
[3 4]]]
(1, 2, 2)
[[[1 2]]
[[3 4]]]
(2, 1, 2)
[[[1]
[2]]
[[3]
[4]]]
(2, 2, 1)
05. 차원 축소
np.sqeeze()
- 차원의 값이 1일 때 제거
# np.sqeeze()
arr = np.array([[1, 2]])
print(arr.shape)
arr2 = np.squeeze(arr)
arr2 = np.squeeze(arr, axis = 0)
# arr2 = np.squeeze(arr, axis = 1) # 차원의 값이 2라서 제거 불가능능
print(arr2.shape)
[출력]
(1, 2)
(2,)
'SKN > 04. Data Analysis' 카테고리의 다른 글
| 05. matplotlib (0) | 2025.03.06 |
|---|---|
| 04. 데이터 결측치 확인 (0) | 2025.03.06 |
| 03. pandas overview (0) | 2025.03.04 |
| 01. numpy overview (1) | 2025.02.28 |