04-1 통계로 요약하기
기술통계: 자료의 내용을 압축하여 설명하는 방법
탐색적 데이터 분석: 데이터 시각화를 아우르는 데이터 분석 방법
기술통계 구하기
03-2절에서 만든 ns_book6.csv 파일 다운로드
import gdown
gdown.download('https://bit.ly/3736JW1', 'ns_book6.csv', quiet=False)
다운로드한 ns_book6.csv 파일을 데이터프레임으로 불러 온 후 처음 5개 행을 출력
import pandas as pd
ns_book6 = pd.read_csv('ns_book6.csv', low_memory=False)
ns_book6.head()
ns_book6 데이터프레임에서 describe() 메서드 호출
ns_book6.describe()
*describe() 메서드: 기본적으로 수치형 열에 대한 요약 통계
- count: 누락된 값을 제외한 데이터 개수를 나타낸다.
- mean: 평균을 구한다.
- std: 표준편차를 구한다.
- min: 최솟값을 구한다.
- 50%: 중앙값을 구한다.
- 25% 와 75%: 순서대로 늘어 놓았을 때 25% 지점과 75% 지점에 놓인 값이다.
- max: 최댓값을 구한다.
불리언 배열과 sum() 함수를 활용하여 도서권수가 0인 도서의 행 개수를 카운트
sum(ns_book6['도서권수']==0)
실제로 없는 도서 대출 데이터 제외
ns_book7 = ns_book6[ns_book6['도서권수']>0]
describe() 메서드: 원하는 위치의 값을 보고 싶다면 percentiles 매개변수에 위치를 지정하면 된다.
ns_book7.describe(percentiles=[0.3, 0.6, 0.9])
object 타입의 열에 대한 통계
ns_book7.describe(include='object')
*다른 데이터 타입의 열의 기술 통계를 보고 싶다면 include 매개변수에 데이터 타입 지정
평균 구하기
평균: 비교적 쉽게 이해할 수 있는 통계량
range() 함수: 하나의 숫자를 입력할 경우 0부터 입력된 숫자 직전까지 반복할 수 있는 객체를 만들어준다.
x = [10, 20, 30]
sum = 0
for i in range(3):
sum += x[i]
print("평균:", sum / len(x))
- mean() 메서드
ns_book7['대출건수'].mean()
중앙값 구하기
- median() 메서드
ns_book7 데이터프레임에서 '대출건수' 열을 선택
ns_book7['대출건수'].median()
데이터 개수가 짝수이면 가운데 두 값을 평균하여 중앙값 결정
temp_df = pd.DataFrame([1,2,3,4])
temp_df.median()
- 중복값 제거하고 중앙값 구하기
drop_duplicates() 메서드를 사용해 '대출건수' 열에서 중복된 값을 가진 행을 제거한 후 중앙값 구하기
ns_book7['대출건수'].drop_duplicates().median()
최솟값, 최댓값 구하기
판다스 min(), max() 메서드
ns_book7['대출건수'].min()
ns_book7['대출건수'].max()
분위수 구하기
분위수: 데이터를 순서대로 늘어 놓았을 때 이를 균등한 간격으로 나누는 기준점
사분위수: 순서대로 정렬된 데이터를 네 구간으로 나눈다.
25%: 제1사분위수
중앙값: 제2사분위수
75%: 제3사분위수
- quantile() 메서드
하위 25%에 위치한 값 출력 → 0.25 입력
ns_book7['대출건수'].quantile(0.25)
여러 개 분위수 지정
ns_book7['대출건수'].quantile([0.25,0.5,0.75])
1,2,3,4,5 다섯 개 숫자가 있을 때 90% 위치에 있는 값 찾기
pd.Series([1,2,3,4,5]).quantile(0.9)
*quantile() 메서드는 interpolation 매개변수에서 중간 값을 계산하는 방법 사용
→ 위 코드는 따로 지정하지 않아서 기본값으로 계산되었다.
*보간: 두 지점 사이에 놓인 특정 위치의 값을 구하는 방법
- 백분위 구하기
'대출건수' 열의 값이 10보다 작은지 비교하여 불리언 배열 만들기
borrow_10_flag = ns_book7['대출건수'] < 10
*borrow_10_flag 배열에서 True인 개수를 모두 헤아린 후 전체 데이터 개수로 나누면 10보다 작은 대출건수의 비율을 얻을 수 있다.
*판다스에서 불리언 자료를 산술 연산하면 True는 1, False는 0으로 취급한다.
mean() 메서드를 호출하여 평균을 구하면 10보다 작은 값이 차지하는 비율을 간단히 얻을 수 있다.
borrow_10_flag.mean()
quantile() 메서드에 백분위를 넣어 확인
ns_book7['대출건수'].quantile(0.65)
분산 구하기
분산: 평균으로부터 데이터가 얼마나 퍼져있는지를 나타내는 통계량
- var() 메서드
대출건수 분산 구하기
ns_book7['대출건수'].var()
표준편차 구하기
표준편차: 분산에 제곱근을 한 것으로 수식 기호는 s를 사용
- std() 메서드
대출건수 표준편차 계산
ns_book7['대출건수'].std()
최빈값 구하기
최빈값: 데이터에서 가장 많이 등장하는 값을 의미
- mode() 메서드
도서명에서 가장 많이 등장하는 값 찾기
ns_book7['도서명'].mode()
수치형에도 적용 가능: 가장 많이 등장하는 연도 알아보기
ns_book7['발행년도'].mode()
데이터프레임에서 기술통계 구하기
수치형 열만 연산할 수 있기 때문에 해당 열에만 적용되도록 numeric_only 매개변수를 True로 지정
ns_book7 데이터프레임에서 mean() 메서드를 호출하면 수치형인 4개의 열에 대한 평균값 계산
ns_book7.mean(numeric_only=True)
*numeric_only 매개변수를 지정하지 않으면 모든 데이터 타입의 열에 대해 수행하기 때문에 시간이 매우 오래 걸린다.
loc 메서드로 '도서명'열부터 마지막 열까지에 대해 최빈값 찾기
ns_book7.loc[:, '도서명':].mode()
ns_book7 데이터프레임을 csv 파일로 저장
ns_book7.to_csv('ns_book7.csv', index=False)
넘파이 기술통계 함수
- 평균 구하기
mean() 함수와 average() 함수 사용
import numpy as np
np.mean(ns_book7['대출건수'])
average() 함수는 weights 매개변수에 가중치를 제공하면 가중 평균 계산
np.average(ns_book7['대출건수'], weights=1/ns_book7['도서권수'])
대출건수 열을 도서권수 열로 나누기
np.mean(ns_book7['대출건수']/ns_book7['도서권수'])
전체 대출건수를 모두 더한 다음 전체 도서권수로 나누기
ns_book7['대출건수'].sum()/ns_book7['도서권수'].sum()
- 중앙값 구하기
median() 함수
np.median(ns_book7['대출건수'])
- 최솟값, 최댓값 구하기
min(), max() 함수
np.min(ns_book7['대출건수'])
np.max(ns_book7['대출건수'])
- 분위수 구하기
quantile() 함수
# interpolation 매개변수가 numpy 1.22(python >= 3.8) 버전부터 method로 바뀜
np.quantile(ns_book7['대출건수'], [0.25,0.5,0.75])
- 분산 구하기
var() 함수
np.var(ns_book7['대출건수'])
*넘파이의 var() 함수는 n으로 나누기 때문에 판다스와 결과가 다르다.
*ddof 매개변수를 사용하여 자유도 차감값 지정
ns_book7['대출건수'].var(ddof=0)
np.var(ns_book7['대출건수'], ddof=1)
- 표준편차 구하기
std() 함수
np.std(ns_book7['대출건수'])
- 최빈값 구하기
직접적으로 최빈값을 계산하는 함수 제공하지 않는다.
unique() 함수는 배열에서 고유한 값을 찾아준다.
return_counts 매개변수를 기본값 False에서 True로 바꿔 주면 고유한 값의 등장 횟수 반환
unique() 함수를 호출해 고유한 값과 등장 횟수 배열 얻기
values, counts = np.unique(ns_book7['도서명'], return_counts=True)
argmax() 함수를 사용하여 counts 배열에서 가장 큰 값의 인덱스 찾기
max_idx = np.argmax(counts)
values 배열에서 해당 인덱스의 값을 출력
values[max_idx]
정리
함수/메서드 | 기능 |
DataFrame.describe() | 데이터프레임의 기술통계량을 출력한다. |
Series.mean() | 데이터에서 평균을 계산한다. |
numpy.mean() | 입력된 배열의 평균을 계산한다. |
Series.median() | 데이터에서 중앙값을 찾는다. |
numpy.median() | 입력된 배열의 중앙값을 찾는다. |
Series.quantile() | 데이터에서 분위수를 계산한다. |
04-2 분포 요약하기
산점도 그리기
산점도: 데이터를 화면에 뿌리듯 그리는 그래프; 두 변수 혹은 두 가지 특성값을 직교 좌표계에 점으로 나타내는 그래프
맷플롯립: 파이썬에서 그래프를 그리는 데 사용하는 대표적인 패키지
# 맷플롯립 3.2.2 버전에서 상자 수염 그림을 그리는데 버그가 있습니다
# 코랩을 사용하시는 경우 matplotlib을 최신 버전으로 업데이트해 주세요.
!pip install -U matplotlib
ns_book7.csv 파일 다운
import gdown
gdown.download('https://bit.ly/3pK7iuu', 'ns_book7.csv', quiet=False)
판다스 데이터프레임으로 불러오기
import pandas as pd
ns_book7 = pd.read_csv('ns_book7.csv', low_memory=False)
ns_book7.head()
맷플롯립에서 제공하는 그래프 함수: matplotlib.pyplot 패키지
import matplotlib.pyplot as plt
- scatter() 함수
함수 첫 번째 매개변수에 4개 포인트의 x축 좌표를 전달하고 두 번째 매개변수에 y축 좌표를 전달
→ show() 함수 호출하여 그래프 출력
plt.scatter([1,2,3,4], [1,2,3,4])
plt.show()
남산도서관 대출 데이터 중에서 '번호'열의 값을 x축에 넣고 '대출건수'열의 값을 y축에 넣기
plt.scatter(ns_book7['번호'], ns_book7['대출건수'])
plt.show()
첫 번째 매개변수에는 x축에 해당하는 '도서권수'열을 지정하고 두 번째 매개변수에는 y축에 해당하는 '대출건수'열 지정
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'])
plt.show()
- 투명도 조절하기
맷플롯립은 alpha 매개변수에 0~1 사이의 값으로 투명도를 지정할 수 있다.
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
*0에 가까울수록 투명하고 1에 가까울수록 불투명하게 그려진다.
*도서권수와 대출건수 사이의 관계란 도서권수가 많으면 대출건수도 많다던가, 도서권수가 적을수록 대출건수가 많다는 식
전자 양의 상관관계, 후자 음의 상관관계
'도서권수'열 대신에 '대출건수'열을 '도서권수'열로 나눈 값을 사용
: 도서권수 당 대출건수를 x축에 놓고 대출건수를 y축에 놓는다.
→ 두 값은 양의 상관관계를 가질 것
'대출건수'열을 '도서권수'열로 나눈 값을 average_borrows 변수에 저장하고, 이 변수와 '대출건수'열을 차례대로 scatter() 함수에 전달
alpha 매개변수는 0.1로 지정
average_borrows = ns_book7['대출건수']/ns_book7['도서권수']
plt.scatter(average_borrows, ns_book7['대출건수'], alpha=0.1)
plt.show()
히스토그램 그리기
히스토그램: 수치형 특성의 값을 일정한 구간으로 나누어 구간 안에 포함된 데이터 개수를 막대 그래프로 그린 것
도수: 구간 안에 속한 데이터 개수
- hist() 함수
: 1차원 데이터를 입력받아 히스토그램을 그리며, 기본적으로 데이터를 10개의 구간으로 나눈다.
bins 매개변수를 5로 지정하여 5개의 구간으로 그리기
plt.hist([0,3,5,6,7,7,9,13], bins=5)
plt.show()
히스토그램의 구간을 정확하게 확인하기 위해 넘파이에서 제공하는 histogram_bin_edges() 함수 사용
: 다섯 구간의 경곗값 출력
import numpy as np
np.histogram_bin_edges([0,3,5,6,7,7,9,13], bins=5)
더 많은 데이터를 가상으로 만들어 히스토그램 그리기
원하는 샘플 개수를 전달하여 난수 생성
np.random.seed(42)
random_samples = np.random.randn(1000)
*randn() 함수: 표준정규분포를 따르는 랜덤한 실수를 생성할 수 있다.
*seed() 함수: 유사난수를 생성할 수 있다.
1,000개 실수로 이루어진 random_samples 배열이 표준정규분포를 따르고 있는지 확인하기 위해 평균와 표준편차 계산
print(np.mean(random_samples), np.std(random_samples))
히스토그램 그려서 종 모양의 분포가 나오는지 확인 → 평균 0을 중심으로 볼록한 종 모양의 분포(전형적인 정규분포 형태)
plt.hist(random_samples)
plt.show()
'대출건수'열의 히스토그램 그리기
plt.hist(ns_book7['대출건수'])
plt.show()
- 구간 조정하기
한 구간의 도수가 너무 커서 다른 구간에는 도수가 표시되지 않는 현상 발생 → y축을 로그 스케일로 바꾸어 해결
로그스케일로 바꾼다는 것은 다음 그림처럼 y축에 로그 함수를 적용한다는 의미
큰 값일수록 도수 크기가 많이 줄어들어 작은 값과의 차이가 줄어든다.
맷플롯립에서 y축을 로그 스케일로 바꾸려면 yscale() 함수에 'log' 지정
plt.hist(ns_book7['대출건수'])
plt.yscale('log')
plt.show()
*맷플롯립은 기본적으로 밑이 10인 로그 함수 사용
x축 구간을 세세하게 나눠보기
: hist() 함수는 기본 10개 구간 사용 → bins 매개변수에서 이를 100으로 바꾸면 데이터 분포를 더 세밀하게 관찰 가능
plt.hist(ns_book7['대출건수'], bins=100)
plt.yscale('log')
plt.show()
'도서명'열에 apply() 메서드를 사용하여 파이썬의 len() 함수를 적용하면 title_len 변수는 각 도서명의 길이가 저장된 판다스 시리즈 객체가 된다.
→ 100개 구간을 가진 히스토그램으로 그리기
title_len = ns_book7['도서명'].apply(len)
plt.hist(title_len, bins=100)
plt.show()
x축에 데이터가 골고루 그려지도록 바꾸기
: xscale() 함수 사용
plt.hist(title_len, bins=100)
plt.xscale('log')
plt.show()
상자 수염 그림 그리기
: 최솟값, 3개의 사분위수, 최댓값 이렇게 5개의 숫자를 사용해 데이터를 요약하는 그래프를 그린다.
*상자 수염 그리는 방법
- 먼저 사분위수를 계산: 25%와 75% 지점을 밑면과 윗면으로 하는 직사각형 그린다.
- 중간값, 즉 50%에 해당하는 지점에 수평선을 긋는다.
- 사각형의 밑면과 윗면에서 사각형의 높이의 1.5배만큼 떨어진 거리 안에서 가장 멀리 있는 샘플까지 수직선을 긋는다.
- 이 수직선 밖에서 최솟값과 최댓값까지 데이터를 점으로 표시 → 이상치
*IQR:제1사분위수와 제3사분위수 사이의 거리
- boxplot() 함수
한 개 이상의 데이터프레임열을 전달하여 그래프 그리기
temp = ns_book7[['대출건수','도서권수']]
plt.boxplot(temp)
plt.show()
보기 좋게 y축을 로그 스케일로 바꾸기
plt.boxplot(ns_book7[['대출건수','도서권수']])
plt.yscale('log')
plt.show()
- 상자 수염 그림 수평으로 그리기
: vert 매개변수를 기본값 True에서 False로 바꾼다.
plt.boxplot(ns_book7[['대출건수','도서권수']], vert=False)
plt.xscale('log')
plt.show()
*x-y축이 바뀌므로 로그 스케일도 x축에 지정해야 한다.
- 수염 길이 조정하기
: 기본적으로 수염의 길이는 IQR의 1.5배 → whis 매개변수에서 조정 가능
IQR의 10배 범위 안에서 가장 멀리 떨어진 데이터까지 수염 그리기
plt.boxplot(ns_book7[['대출건수','도서권수']], whis=10)
plt.yscale('log')
plt.show()
whis 매개변수는 백분율로도 지정 가능
(0, 100)으로 지정하여 마지막 데이터까지 수염 그리기
plt.boxplot(ns_book7[['대출건수','도서권수']], whis=(0,100))
plt.yscale('log')
plt.show()
판다스의 그래프 함수
- 산점도 그리기
scatter() 메서드: x축과 y축에 해당하는 열 이름만 지정
ns_book7.plot.scatter('도서권수', '대출건수', alpha=0.1)
plt.show()
*열 이름이 한글일 때는 실행 결과처럼 제대로 출력되지 않는다.
- 히스토그램 그리기
: 데이터프레임에 apply() 메서드를 적용한 다음 이어서 바로 plot.hist() 메서드를 호출
ns_book7['도서명'].apply(len).plot.hist(bins=100)
plt.show()
- 상자 수염 그림 그리기
: boxplot() 메서드
ns_book7[['대출건수','도서권수']].boxplot()
plt.yscale('log')
plt.show()
정리
함수/메서드 | 기능 |
Matplotlib.pyplot.scatter() | 2차원 평면에 산점도를 그린다. |
Matplotlib.pyplot.hist() | 히스토그램을 그린다. |
Matplotlib.pyplot.boxplot() | 상자 수염 그림을 그린다. |
Matplotlib.pyplot.xscale() | x축의 스케일을 지정한다. |
Matplotlib.pyplot.yscale() | y축의 스케일을 지정한다. |
numpy.random.seed() | 원하는 임의의 정수를 입력하면 난수 발생을 동일하게 재현할 수 있다. |
numpy.random.randn() | 표준정규분포를 따르는 난수를 생성한다. |
'혼자 공부하는 데이터 분석' 카테고리의 다른 글
6장 복잡한 데이터 표현하기 (0) | 2023.06.08 |
---|---|
5장 데이터 시각화하기 (1) | 2023.05.29 |
3장 데이터 정제하기 (0) | 2023.05.22 |
2장 데이터 수집하기 (0) | 2023.05.14 |
1장 데이터 분석을 시작하며 (0) | 2023.05.12 |
댓글