[혼공분석] 4주차: 데이터 요약하기
벌써 4주차라니..!
50% 완주란 말에 더 뿌듯하게 시작한 4주차!
이제 완주까지도 얼마 안 남았구나..
Chapter 04. 데이터 요약하기
04-1. 통계로 요약하기
기술통계(요약 통계)
: 자료의 내용을 압축하여 설명하는 방법
통계량
: 평균, 표준편차 등 표본의 특징을 수치화한
탐색적 테이터 분석
: 데이터 시각화를 아우르는 이러한 데이터 분석 방법
기술 통계 구하기
- describe( ) 메서드: 데이터프레임의기술통계량 출력
df.describe( percentile=[ ] , incllude=, exclude= )
percentile=[ ] : 출력할 분위수를 0 ~ 1 사이로 지정 (기본값: [0.25, 0.5, 0.75])
include= : 기술통계 계산에 포함할 데이터 타입 지정
→ 기본적으로는 수치형에 대한 기술통계 계산
exclude= : 기술통계 계산에 제외할 데이터 타입 지정 → 기본적으로는 아무것도 제외하지 않음
ns_book6.describe()
- count: 누락된 값을 제외한 데이터 개수
- mean: 평균
- std: 표준편차
- min: 최솟값
- 50%: 중앙값
- 25%: 순서대로 놓았을 때 25% 지점에 놓인 값
- 75%: 순서대로 놓았을 때 75% 지점에 놓인 값
- max: 최댓값
→ 대출건수의 평균값은 약 11.5 !
→ 발행년도의 최솟값은 1947 !
→ 도서권수의 최솟값은 0 ? 도서를 가지고 있지 않은데 대출 데이터에 포함되어 있는 것 !
sum(ns_book6['도서권수']==0)
ns_book7 = ns_book6[ns_book6['도서권수']>0]
분석 시 제외 여부 판단하여 0권인 책 제외
ns_book7.describe()
ns_book7.describe(percentiles=[0.3, 0.6, 0.9]) #30%, 60%, 90% 위치한 값 표시
ns_book7.describe(include='object')
평균 구하기
수식 속 x가 반복 → 반복문을 사용하여 구현
x = [10, 20, 30]
sum = 0
for i in range(3): #0부터 입력된 3 직전 값인 2까지 i에 대입하여 실행
sum+= x[i]
print("평균:", sum/len(x))
- mean( ) 메서드: 데이터에서 평균 계산
ns_book7['대출건수'].mean()
중앙값 구하기
- median( ) 메서드: 데이터에서 중앙값 찾음
ns_book7['대출건수'].median()
# 데이터 개수가 짝수인 경우
temp_df = pd.DataFrame([1,2,3,4])
temp_df.median()
#중복값 제거 후 중앙값
ns_book7['대출건수'].drop_duplicates().median()
최솟값 구하기
- min( ) 메서드: 데이터에서 최솟값 찾음
ns_book7['대출건수'].min()
최댓값 구하기
- max( ) 메서드: 데이터에서 최솟값 찾음
ns_book7['대출건수'].max()
분위수 구하기
분위수
: 데이터를 순서대로 늘어 놓았을 때 이를 균등한 간격으로 나누는 기준점
사분위수
: 데이터를 순서대로 늫어 놓았을 때 4개의 구간으로 나누는 기준점
- quantile( ) 메서드: 데이터에서 분위수 계산
.quantile( q 매개변수 , interpolation= )
q 매개변수: 계산할 분위수를 0 ~ 1 사이로 지정 (기본값: 0.5)
interpolation = 'linear': 인접한 두 데이터 포인트의 거리에 비례하여 분위수 계산 (기본값)
interpolation = 'lower': 작은 값 선택
interpolation = 'higher': 큰 값 선택
interpolation = 'nearest': 가까운 값 선택
interpolation = 'midpoint': 중간값 선택
ns_book7['대출건수'].quantile(0.25) #하위 25% 값 출력
ns_book7['대출건수'].quantile([0.25,0.5,0.75]) #여러 개의 분위수 지정 가능
보간
: 두 지점 사이에 놓인 특정 위치의 값을 구하는 방법
pd.Series([1,2,3,4,5]).quantile(0.9)
시리즈 객체에 없는 4.6이란 값 출력 !?
90%에 해당하는 값은 4(0.75)와 5(1.0)사이에 위치 → 4와 5사이의 90% 지점
≫ 0.6
[1, 2, 3, 4, 5] 에서 하위 90%에 위치한 값 = 4.6
백분위 구하기: 대출건수 10이 위치한 백분위 찾기
'대출건수' 열의 값이 10보다 작은지 비교하는 불리언 배열 생성
10보다 작으면 True (1)
10보다 크면 False (0)
→ True인 개수를 센 다음 전체 데이터 개수로 나누면 10보다 작은 대출 건수의 비율을 얻음
→ 데이터 양이 많으면 전체 데이터를 순서대로 놓았을 때 10이 위치한 백분위와 거의 비슷
#'대출건수' 열의 값이 10보다 작은지 비교하는 불리언 배열
borrow_10_flag = ns_book7['대출건수'] < 10
borrow_10_flag.mean()
ns_book7['대출건수'].quantile(0.65)
분산 구하기
분산
: 평균으로부터 데이터가 얼마나 퍼져있는지를 나타내는 통계량
→ 데이터가 가운데 모여 있다 = 분산이 작다
→ 데이터가 넓게 퍼져 있다 = 분산이 크다
데이터의 각 값에서 평균을 뺀 다음 제곱한 후 평균처럼 샘플 개수로 나누어 구함
- var( ) 메서드: 데이터의 분산 계산
ns_book7['대출건수'].var()
표준편차 구하기
표준편차(s)
: 분산에 제곱근을 한 것
- std( ) 메서드: 데이터의 표준편차 계산
ns_book7['대출건수'].std()
최빈값 구하기
- mode( ) 메서드: 데이터의 최빈값 찾음
ns_book7['도서명'].mode()
ns_book7['발행년도'].mode() #수치형에도 적용 가능
*데이터프레임에서 기술통계 구할 시, mumeric_only = True 지정
ex) ns_book7.mean(numeric_only = True)
04-2. 분포 요약하기
산점도
: 데이터를 화면에 뿌리듯 그리는 그래프
→ 두 변수 혹은 두 가지 특성 값을 직교 좌표계에 점으로 나타내는 그래프
- 맷플롤립(matplotlib)
import matplotlib.pyplot as plt
scatter( ) 함수
plt.scatter(x축 좌표, y축 좌표, alpha=)
alpha= : 0 ~ 1 사이의 실수를 지정하여 점의 투명도 설정
→ 0에 가까울수록 투명하고 1에 가까울수록 불투명
plt.scatter([1,2,3,4], [1,2,3,4])
plt.show()
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'])
plt.show()
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
average_borrows = ns_book7['대출건수']/ns_book7['도서권수']
plt.scatter(average_borrows, ns_book7['대출건수'], alpha=0.1)
plt.show()
양의 상관관계
: 한 값이 증가 시 다른 값도 증가
음의 상관관계
: 한 값이 증가 시 다른 값은 감소
히스토그램
: 수치형 특성의 값을 일정한 구간으로 나누어 구간 안에 포함된 데이터 개수를 막대 그래프로 그린 것
도수
: 구간 안에 속한 데이터 개수
hist( ) 함수
.hist(데이터, bins=, log=)
bins= :구간 개수 결정 (기본값 10)
log= True: 로그 스케일로 그림(기본값 Fasle)
plt.hist([0,3,5,6,7,7,9,13], bins=5)
plt.show()
#구간 경계값 출력
import numpy as np
np.histogram_bin_edges([0,3,5,6,7,7,9,13], bins=5)
plt.hist(ns_book7['대출건수'])
plt.show()
첫 번째 구간의 도수가 너무 커서 다른 구간에는 도수 값이 표시되지 않는 현상 발생! → 구간 조정
y축을 로그 스케일로 바꾸어 해결
로그 스캐일로 바꾼다? → y축에 로그 함수를 적용한다
→ 큰 값일수록 도수 크기가 많이 줄어 작은 값과의 차이 줄어든다 !
plt.hist(ns_book7['대출건수'])
plt.yscale('log')
plt.show()
plt.hist(ns_book7['대출건수'], log=True) #log 매개변수 사용
plt.show()
title_len = ns_book7['도서명'].str.len()
plt.hist(title_len, bins=100)
plt.xscale('log') #xscale() 함수로 x축에도 로그 스케일 적용
plt.show()
상자 수염 그림
: 최솟값, 세 개의 사분위수, 최댓값을 사용해 데이터를 요약하는 그래프를 그림
- 사분위값 계산 후 25%와 75% 지점을 밑면과 윗면으로 하는 직사각형을 그림 (25%와 75% 사이의 거리를 IQR)
- 중간값(50% 지점)에 해당하는 지점에 수평선을 그림
- 사각형의 밑면과 윗면에서 사각형의 높이의 1.5배만큼 떨어진 거리 안에서 가장 멀리 있는 샘플까지 수직선 그림
- 3에서 그린 수직선 밖에서 최솟값과 최댓값까지 데이터를 점으로 표시 (이 영역의 데이터가 이상치)
boxplot( ) 함수
.boxplot(데이터, vert= , whis= )vert=False: 수평 방향vert=True: 수직 방향 (기본값)whis= : 수염 길이 결정 (기본값 1.5)
plt.boxplot(ns_book7[['대출건수','도서권수']])
plt.show()
1번 상자(대출건수)와 2번 상자(도서권수) 데이터는 사분위수가 매우 작아 직사각형 상자가 거의 보이지 않음
붉은 수평선으로 중간값 표시
plt.boxplot(ns_book7[['대출건수','도서권수']])
plt.yscale('log') #y축 로그 스케일로
plt.show()
1번 상자(대출건수)는 상자 모양 확인 가능, 2번 상자(도서권수)는 여전히 상자 모양 확인 불가능
→ 도서권수 열의 사분위수가 모두 1이기 때문에 상자가 보이지 않는게 맞음!
#상자 수염 그림 수평으로 그리기
plt.boxplot(ns_book7[['대출건수','도서권수']], vert=False)
plt.xscale('log')
plt.show()
#수염 길이 조정하기
plt.boxplot(ns_book7[['대출건수','도서권수']], whis=10)
plt.yscale('log')
plt.show()
plt.boxplot(ns_book7[['대출건수','도서권수']], whis=(0,100)) #0%, 100% 백분위수에 해당하는 데이터 수염 그림
plt.yscale('log')
plt.show()
기본 숙제
selected_rows = (ns_book7['발행년도'] >= 1980) & (ns_book7['발행년도'] <= 2022)
plt.hist(ns_book7.loc[selceted_rows, '발행년도'])
plt.show()
추가 숙제: 기술통계량 개념 정리
본문에 정리 완.