혼공학습단 13기

[혼공분석] 4주차: 데이터 요약하기

zer0zero 2025. 2. 9. 23:54

벌써 4주차라니..!

50% 완주란 말에 더 뿌듯하게 시작한 4주차!

이제 완주까지도 얼마 안 남았구나..

Chapter 04. 데이터 요약하기

04-1. 통계로 요약하기


기술통계(요약 통계): 자료의 내용을 압축하여 설명하는 방법

통계량: 평균, 표준편차 등 표본의 특징을 수치화한 

탐색적 테이터 분석: 데이터 시각화를 아우르는 이러한 데이터 분석 방법

 

[ns_book6] 3주차에 만들었던 csv 파일

 

기술 통계 구하기

- 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)

3206 개의 책의 권수가 0

ns_book7 = ns_book6[ns_book6['도서권수']>0]

분석 시 제외 여부 판단하여 0권인 책 제외

ns_book7.describe()

도서권수의 최솟값(min) 바뀐 것 확인

ns_book7.describe(percentiles=[0.3, 0.6, 0.9]) #30%, 60%, 90% 위치한 값 표시

 

ns_book7.describe(include='object')

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()

 

 

 

상자 수염 그림: 최솟값, 세 개의 사분위수, 최댓값을 사용해 데이터를 요약하는 그래프를 그림

  1. 사분위값 계산 후 25%와 75% 지점을 밑면과 윗면으로 하는 직사각형을 그림 (25%와 75% 사이의 거리를 IQR)
  2. 중간값(50% 지점)에 해당하는 지점에 수평선을 그림
  3. 사각형의 밑면과 윗면에서 사각형의 높이의 1.5배만큼 떨어진 거리 안에서 가장 멀리 있는 샘플까지 수직선 그림
  4. 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()

추가 숙제: 기술통계량 개념 정리

본문에 정리 완.