머신러닝

SEABORN

haniru 2026. 1. 7. 23:59

1. Seaborn의 핵심 가치: 통계적 시각화

  • Matplotlib 기반: 모든 Seaborn 그래프는 Matplotlib 객체다. 따라서 세밀한 조정은 Matplotlib 문법을 섞어 쓸 수 있다.
  • 데이터 프레임 친화적: Pandas 데이터 프레임의 컬럼 이름을 직접 지정해 그래프를 그릴 수 있어 직관적이다.
  • 통계 내장: 데이터의 평균, 신뢰구간, 밀도 추정(KDE) 등을 별도 계산 없이 자동으로 그려준다.

2. 데이터 분석의 첫걸음: 특성(Feature) 이해

데이터를 받으면 가장 먼저 컬럼(특성)들이 무엇을 의미하는지 봐야 한다.

예시 데이터 독립변수 (Feature, 특성) 종속변수 (Target, Label) 분석 포인트
보스톤 주택 방 개수, 범죄율, 면적, 학군 주택 가격 어떤 특성이 가격에 가장 큰 영향을 주는가?
아이리스(붓꽃) 꽃잎/꽃받침의 너비와 길이 꽃의 품종 4개 특성의 조합으로 품종을 구별할 수 있는가?
개 품종 몸통 길이, 다리 높이, 귀 모양 품종 (리트리버/푸들) 신체적 특성이 품종 분류의 기준이 되는가?

 

독립변수는 가설에서 원인이 되는 변수이고, 종속변수는 그 원인에 따라 결과값이 결정되는 결과 변수다.

  • 가설 1: 평균 기온이 올라가면 수영복 판매량이 증가할 것이다.
    • 독립변수: 평균 기온 (원인)
    • 종속변수: 수영복 판매량 (결과)
  • 가설 2: 국민 1인당 GDP가 높아지면 1인당 해외 여행비 지출이 증가할 것이다.
    • 독립변수: 국민 1인당 GDP (원인)
    • 종속변수: 1인당 해외 여행비 지출 (결과)
  • 가설 3: 소득이 높은 가구일수록 거주하는 주택의 가격이 비쌀 것이다.
    • 독립변수: 가구 소득 (원인)
    • 종속변수: 주택 가격 (결과)
  • 가설 4: 공부를 오래 한 학생일수록 시험 성적이 더 높을 것이다.
    • 독립변수: 공부 시간 (원인)
    • 종속변수: 시험 성적 (결과)

3. 통계적 변수 관계

메모한 독립변수와 종속변수의 개념은 머신러닝 모델을 설계할 때 그대로 이어진다.

  • 독립변수 (Independent Variable, $x$): * 모델의 입력값.
    • 연구자가 임의로 조절하거나 관찰하는 원인.
    • 예: "공부 시간", "주택 면적".
  • 종속변수 (Dependent Variable, $y$): * 모델의 결과값/예측값.
    • 독립변수의 변화에 따라 반응하는 결과.
    • 예: "시험 점수", "집값".

4. Seaborn 주요 함수 체계

Seaborn은 데이터의 성격에 따라 세 가지 대표적인 API를 제공한다.

  1. relplot() (Relational): 수치형 변수 간의 관계(상관관계)를 그릴 때 사용 (Scatter, Line).
  2. displot() (Distribution): 데이터가 어디에 분포해 있는지 볼 때 사용 (Histogram, KDE).
  3. catplot() (Categorical): 범주형 데이터(예: 성별, 품종)의 수치를 비교할 때 사용 (Bar, Box, Violin).

5. 상관관계 vs 인과관계 (Correlation vs Causality)

  • 상관관계: 두 변수 xy가 같이 움직이는 경향성. 하나가 증가할 때 다른 하나도 증가하거나(양), 감소하는(음) 현상을 말한다.
  • 인과관계: x가 원인이 되어 y라는 결과를 직접적으로 만들어내는 관계.
  • 주의점: 상관관계가 높다고 해서 반드시 원인과 결과인 것은 아니다. 아이스크림 예시에서 진짜 원인은 '폭염'이라는 외부 요인이다.

6. 피어슨 상관계수 (r)

데이터 사이의 선형적인 관계를 수치화한 것이다. 값의 범위는 항상 -1에서 1 사이에 존재한다.

계수 값 의미
r = 1.0 완벽한 양의 선형 관계 (한 치의 오차 없이 직선상에 위치)
r = -1.0 완벽한 음의 선형 관계
r = 0.0 선형적인 상관관계가 전혀 없음 (독립적임)
0.3 ~ 0.7 뚜렷한 상관관계가 있음

 

코드

상관계수 행렬

  • 행렬 의미: * [0, 0]: x x 자신의 관계 (당연히 1.0)
    • [0, 1]: x y1의 상관계수 (1.0)
    • [1, 0]: y1 x의 상관계수 (1.0)
    • [1, 1]: y1 y1 자신의 관계 (당연히 1.0)
  • y = 2x는 완벽한 일차함수 직선이므로 상관계수는 소수점 끝까지 1.0이 찍힌다.
import numpy as np
np.random.seed(85)
x = np.arange(0, 10)
y1 = x * 2 # 2는 weight(계수) 2배수가 됨
np.corrcoef(x, y1)

 

 

 

 

상관계수 행렬

1. 피어슨 상관계수(Pearson Correlation)의 특징

작성한 코드에서 사용한 np.corrcoef는 피어슨 상관계수를 계산함. 이 계수는 두 변수 사이의 선형적(직선) 관계가 얼마나 강한지를 측정함.

  • 선형성(Linearity): 피어슨 상관계수는 데이터가 '직선'에 가까울수록 1에 가까워짐.
  • 곡선 관계: y = x***3은 직선이 아닌 가파르게 상승하는 곡선임. 따라서 y = 2x와 같은 직선 관계보다는 상관계수가 낮게 나오지만, 여전히 양의 방향으로 강하게 움직이므로 0.908이라는 높은 수치가 나타남.

2. 선형성 vs 단조성 (Linearity vs Monotonicity)

데이터 분석에서 이 차이를 이해하는 것이 중요함.

  • 선형 관계: x가 일정하게 증가할 때 y도 일정하게 증가함 (예: y = ax + b). 피어슨 상관계수가 1임.
  • 단조 관계: x가 증가할 때 y도 '어쨌든' 항상 증가함. $y = x***3은 완벽한 단조 관계임.
    • 만약 선형성이 아닌 순위나 방향성만을 따지는 스피어만(Spearman) 상관계수를 구했다면, 곡선이더라도 항상 증가하기 때문에 1.0이 나왔을 것임.
x = np.arange(0, 10)
y2 = x ** 3 # 세제곱 그래프 그려줘
#양의 방향으로 감
np.corrcoef(x, y2)

 

상관계수 행렬과 이를 시각화한 히트맵

  • 밝은 색 (흰색/노란색): 상관계수가 $1$에 가까울수록 밝게 표시된다. 대각선이 가장 밝게 나타나는 이유다.
  • 어두운 색 (검은색/빨간색): 상관계수가 $0$에 가깝거나 음수일수록 어둡게 표시된다. 이를 통해 어떤 변수끼리 관계가 없는지 한눈에 파악할 수 있다.
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(85)
# 1은 가장 밝음
x = np.arange(0, 10) # 0에서 9사이의 연속적인 수
y2 = x ** 3
y3 = np.random.randint(0, 100, size=10) # 0에서 1000사이 10개 난수
result = np.corrcoef(x, y3)
print(result)
# -0.05면 관계가 거의 없는 것 -> 랜덤값은 상관관계가 거의 없다
result2 = np.corrcoef((x,y2,y3))
# 밝으면 밝을수록 높은값
print(result2)

plt.imshow(result2)
plt.colorbar()

 

seaborn

sns.pairplot(df)의 시각적 구성

  • 대각선 구간: 자기 자신과의 관계이므로 산점도가 아닌 히스토그램 또는 **밀도 추정 곡선(KDE)**을 그려 해당 변수가 어떻게 분포되어 있는지 보여준다.
  • 비대각선 구간: 두 변수 사이의 **산점도(Scatter Plot)**를 그린다. 여기서 점들이 직선에 가까운지, 곡선인지, 아니면 아무 관계가 없는지 한눈에 확인할 수 있다.
  • 상관관계와의 연결: x와 y2의 상관계수가 0.908이었으므로, 페어플롯 상에서도 두 변수의 관계는 아주 뚜렷한 곡선 혹은 직선에 가까운 형태로 나타난다.
import seaborn as sns
import pandas as pd

df = pd.DataFrame({'x': x, 'y2':y2, 'y3':y3}) # 딕셔너리

sns.pairplot(df)

 

자료구조에 대한 통찰

작성한 메모 중 파이썬 자료구조의 특징을 데이터 분석 관점에서 정리한다.

  • 딕셔너리(Dictionary)와 데이터프레임:
    • pd.DataFrame(dict) 방식은 가장 많이 쓰이는 생성법이다.
    • 딕셔너리는 해시 테이블(Hash Table) 구조를 사용하므로 데이터 탐색 속도가 매우 빠르다($O(1)$). 메모에 적힌 이진 트리 구조보다 더 빠른 탐색 성능을 보장하는 방식이다.
  • 튜플(Tuple)의 불변성(Immutable):
    • 튜플은 생성 후 수정이 불가능하다. 이는 데이터 분석 시 좌표값이나 설정값처럼 변해서는 안 되는 중요한 정보를 보호할 때 유리하다.
    • 수정은 안 되지만 리스트보다 메모리 사용이 적고 처리 속도가 빠르다는 장점이 있다.
  • 가변성(Mutable) 주의사항:
    • 리스트나 딕셔너리처럼 내용을 바꿀 수 있는 객체는 함수 내부에서 값이 변할 경우 원본 데이터까지 영향을 줄 수 있어 주의가 필요하다. 그래서 데이터 안정성을 위해 튜플이나 데이터프레임의 복사본(copy)을 사용하라는 권고가 많다.

 

Seaborn의 **relplot**

1. tips 데이터셋 이해

Seaborn에서 기본 제공하는 tips 데이터셋은 레스토랑 손님들의 정보를 담고 있다.

  • total_bill: 전체 식사 금액 (독립변수 역할)
  • tip: 팁 금액 (종속변수 역할)
  • smoker: 흡연 여부 (범주형 데이터)
  • time: 식사 시간 (Lunch/Dinner)
  • size: 동행 인원수

2. relplot의 핵심 파라미터

relplot은 여러 변수의 관계를 한 차트 내에 다채롭게 표현할 수 있도록 다양한 옵션을 제공한다.

  • hue (색상): 특정 컬럼(smoker)의 값에 따라 점의 색상을 다르게 표현함.
  • style (모양): 값에 따라 점의 모양(X, O 등)을 다르게 설정함. hue와 함께 쓰면 구분이 더 명확해짐.
  • size (크기): 값의 크기(size, 인원수)에 따라 점의 크기를 조절하여 데이터의 양적 차이를 시각화함.
  • col (열 분할): 특정 조건(time)에 따라 그래프를 여러 개의 서브플롯으로 나누어 그림. 한 화면에서 '점심'과 '저녁' 데이터를 분리해서 비교하기 좋음.

3. 데이터 분석 인사이트

전체 금액과 팁의 상관관계

  • 양의 상관관계: 작성한 메모대로 total_bill이 커질수록 tip도 증가하는 경향을 보임. 이는 선형적인 관계가 있음을 시사함.

흡연 여부에 따른 차이

  • 데이터의 분포: 흡연자(smoker="Yes")와 비흡연자(smoker="No")를 색상으로 구분했을 때, 특정 그룹이 팁을 더 후하게 주거나 혹은 금액 대비 팁 비율이 높은지 패턴을 확인할 수 있음.
  • 변동성: 일반적으로 흡연자 그룹은 팁의 편차(변동성)가 비흡연자 그룹보다 더 크게 나타나는 경향이 있음.
# 시본 라이브러리 시작하기
import seaborn as sns

sns.set_theme(style="darkgrid")
tips = sns.load_dataset("tips")
print(tips.head()) # 5개만 뜸
sns.relplot(data=tips, x="total_bill", y="tip", col="time", hue="smoker", style="smoker", size="size")

# 청구금액이 클수록 팁이 크다
sns.relplot(x="total_bill", y="tip", data=tips)

# 양의 관계, 일반적으로 흡연자 그룹은 팁의 편차(변동성)가 비흡연자 그룹보다 더 크게 나타나는 경향
sns.relplot(x="total_bill", y="tip", hue="smoker", data=tips)

 

 

Seaborn의 relplot을 사용하여 **5개 이상의 변수(total_bill, tip, time, smoker, size)**를 하나의 그림에 표현

Seaborn relplot을 활용한 다차원 데이터 분석


1. 시각화 결과 해석 및 사용자 관찰 확인

  • col="time"의 효과: 점심(Lunch)과 저녁(Dinner) 데이터를 별도의 그래프로 분리하여 비교할 수 있게 한다.
  • 저녁 시간대 특징: 작성한 메모대로 저녁 시간의 데이터 포인트들이 오른쪽 상단으로 더 넓게 퍼져 있다. 이는 저녁에 식사 금액(total_bill)이 높고, 결과적으로 더 많은 팁(tip)이 발생한다는 사실을 뒷받침한다.
  • 흡연 여부와 팁: hue와 style을 모두 smoker로 지정하여 흡연자와 비흡연자의 차이를 색상과 모양으로 명확히 구분했다.

2. 사용된 파라미터의 역할 요약

파라미터 역할 분석적 의미
x, y x축, y축 지정 금액과 팁 사이의 양의 상관관계 확인
col 열 분할 시간대별(Lunch/Dinner) 소비 패턴 차이 분석
hue & style 색상 및 모양 흡연 여부에 따른 데이터 군집(Cluster) 구분
size 점의 크기 방문 인원수에 따른 수치 변화 시각화
import seaborn as sns

# 테마를 설정하는 기능이 있음
sns.set_theme(style="darkgrid")
# 시본에서 제공하는 팁 데이터를 가져오자
tips = sns.load_dataset("tips")

# 팁 데이터의 시각화 기능을 호출하자
sns.relplot(data=tips, x="total_bill", y="tip", col="time",
            hue="smoker", style="smoker", size="size")

# 디너 타임에 팁을 많이 준다

 

팁(tip) 데이터의 분포를 한눈에 파악하기 위한 히스토그램

 

  • 최빈값(Mode) 확인: 가장 높게 솟은 막대가 있는 구간(보통 2~3달러 사이)이 손님들이 가장 흔하게 주는 팁 금액이다.
  • 우측 꼬리 분포(Right-Skewed): 대부분의 팁은 낮은 금액대에 몰려 있고, 10달러에 가까운 고액 팁으로 갈수록 막대의 높이가 급격히 낮아지는 '긴 꼬리' 형태를 보일 것이다.
  • 이상치(Outlier) 감지: 10개 구간 중 혼자 멀리 떨어져 있는 작은 막대가 있다면, 그것은 특별히 후한 서비스에 대한 보상이었을 가능성이 크다.

 

sns.histplot(tips['tip'], kde=False, bins=10);

 

식사 금액 대비 팁의 비율(tip_pct)을 계산하여 분포를 시각화

 

  • 평균적 팁 비율: 대부분의 점이 특정 구간(보통 15% 내외)에 집중되어 있을 것이다. 미국 레스토랑 문화에서 통용되는 관습적인 팁 비율이 그래프의 피크(Peak)로 나타난다.
  • 이상치(Outlier) 확인: 30%나 40%가 넘는 높은 비율에 위치한 작은 막대들은 매우 만족스러운 서비스였거나, 식사 금액 자체가 적어 비율이 상대적으로 높게 산출된 경우일 수 있다.
  • 분포의 비대칭성: 왼쪽(0% 근처)보다는 오른쪽(높은 비율)으로 꼬리가 길게 늘어지는 우측 편향(Right-skewed) 분포를 보일 가능성이 크다.

 

tips['tip_pct'] = 100 * tips['tip'] / tips['total_bill']
sns.histplot(tips['tip_pct'], kde=True, bins=20)

 

산점도 그래프

 

  • 시각적 패턴: x축(식사 금액)이 증가함에 따라 y축(팁)도 대체로 증가하는 양의 상관관계를 뚜렷하게 보여준다.
  • 데이터 분포: 금액이 커질수록 팁의 분산(퍼짐 정도)도 함께 커지는 경향이 있다. 이는 '식사 금액이 높을수록 팁을 더 많이 줄 것이다'라는 가설을 시각적으로 뒷받침한다.

 

sns.relplot(x='total_bill', y='tip', data=tips)

 

식사 금액(total_bill)과 팁(tip)의 상관관계 시각화

sns.relplot(x='total_bill', y='tip', hue='smoker',\
            style='smoker', data=tips)

 

5개 이상의 변수(금액, 팁, 시간, 흡연 여부, 인원수)를 하나의 그림에 통합하여 데이터 사이의 복잡한 관계를 분석

 

  • 다차원 관계 파악: 단순한 산점도를 넘어, '저녁 시간(col)에 방문한 비흡연자(hue/style) 대가족(size)'이 팁을 어떻게 주는지 한눈에 읽을 수 있다.
  • 상관관계의 전이: 전체적으로 우상향하는 양의 상관관계가 나타나지만, col="time" 설정을 통해 저녁 시간대에 데이터가 더 넓게 퍼져 있고(분산이 큼) 고액 결제가 많음을 알 수 있다.
  • 이상치 식별: 다른 점들과 달리 혼자 크기가 아주 크거나(많은 인원), 특정 색상에서 튀는 위치에 있는 점을 찾아내기 쉽다.

 

sns.relplot(data=tips, x="total_bill", y="tip", col="time",
            hue="smoker", style="smoker", size="size")
파라미터 데이터 속성 시각적 변화 분석적 의의
x, y 수치형 (금액, 팁) 좌표축 위치 두 변수 사이의 상관관계 확인
col 범주형 (시간) 그래프 분할 점심 vs 저녁 간의 패턴 차이 비교
hue 범주형 (흡연) 색상 그룹별 군집(Cluster) 형성 여부 파악
style 범주형 (흡연) 모양 색상과 병행하여 그룹 구분 명확화
size 수치형 (인원수) 점의 크기 데이터의 양적 가중치 시각화

 

  • 독립변수 (x$: total_bill. 팁 액수에 영향을 주는 원인이다.
  • 종속변수 (y): tip. 식사 금액에 따라 결과가 달라지는 변수다.
  • 통제/분류 변수: time, smoker, size. 특정 조건에서 상관관계가 어떻게 변하는지 보여주는 보조 변수들이다.

 

산점도 위에 **선형 회귀 직선(Linear Regression Line)**을 추가하여 데이터의 경향성을 시각화하는 방식

 

  • 산점도(Scatter Plot): 개별 데이터 포인트들을 좌표평면에 나타낸다.
  • 회귀 직선(Regression Line): 데이터를 가장 잘 설명하는 직선 y = ax + b를 그려준다. 이 직선의 기울기는 두 변수 사이의 상관관계 방향을 나타낸다.
  • 신뢰 구간(Confidence Interval): 직선 주위의 반투명한 그림자 영역이다. 기본적으로 95% 신뢰 구간을 표시하며, 데이터가 밀집될수록 좁아진다.

 

ax = sns.regplot(data=tips, x='total_bill', y='tip')
ax.set_xlabel('Total Bill')  # x 축의 레이블
ax.set_ylabel('Tip')         # y 축의 레이블
ax.set_title('Total Bill and Tip')   # 그림의 제목

 

 

쌍그래프

sns.pairplot(tips)

1. 주요 변수 간의 상관관계 (산점도 분석)

  • total_bill vs tip (강한 양의 상관관계): 전체 식사 금액이 커질수록 팁 액수도 늘어나는 뚜렷한 경향을 보임. 데이터가 우상향하는 직선 형태로 분포함.
  • total_bill vs size (양의 상관관계): 일행 수(size)가 많을수록 전체 주문 금액이 커지는 경향이 있음. 당연한 결과지만, 인원수가 고정된 이산형 데이터라 계단식 분포를 보임.
  • total_bill vs tip_pct (음의 상관관계 혹은 일정함): 결제 금액이 커진다고 해서 팁 비율(tip_pct)까지 높아지지는 않음. 오히려 결제 금액이 아주 적을 때 팁 비율이 비정상적으로 높은 경우(아웃라이어)가 관찰됨.
  • tip vs tip_pct: 팁 액수와 팁 비율 사이에는 명확한 선형 관계가 보이지 않음. 특정 구간에 데이터가 밀집되어 있음.

2. 개별 변수의 분포 (대각선 히스토그램 분석)

  • total_bill & tip: 두 변수 모두 오른쪽으로 꼬리가 긴(right-skewed) 분포를 가짐. 즉, 낮은 금액의 결제와 팁이 대다수이며 고액 결제는 드묾.
  • size: 2인 손님이 압도적으로 많으며, 1인 또는 5~6인 단체 손님은 상대적으로 매우 적음.
  • tip_pct: 대부분 15%~20% 사이에 밀집되어 있음. 팁 문화의 전형적인 비율을 반영함.

3. 특이사항 및 아웃라이어

  • tip_pct의 이상치: tip_pct 히스토그램과 산점도를 보면 70%에 육박하는 비정상적으로 높은 팁 비율이 하나 존재함. 이는 적은 금액의 식사를 하고 상대적으로 큰 팁을 준 경우로 해석됨.
  • 고액 결제: total_bill이 40~50달러를 넘어가는 고액 결제 구간에서도 팁은 어느 정도 일정 수준(10달러 내외)에서 수렴하는 경향이 있음.

앤스콤의 콰르텟

1. 그래프의 구성 요소

  • 점 (Scatter Plot): 실제 데이터 값을 나타낸다. x값이 얼마일 때 y값이 얼마인지 찍어 놓은 것이다.
  • 직선 (Regression Line): 데이터의 전체적인 '추세'를 가장 잘 나타낸다고 판단되는 선을 컴퓨터가 계산해서 그린 것이다. "대충 이런 방향으로 움직인다"는 것을 보여준다.

2. 첫 번째 그래프 (Dataset I) 분석

첫 번째 이미지의 데이터는 우리가 흔히 생각하는 **'전형적인 상관관계'**를 보여준다.

  • 특징: 점들이 직선 주변에 적당히 흩어져 있다.
  • 의미: x가 커질수록 y도 함께 커지는 경향이 뚜렷하다. 이 경우 직선(추세선)은 데이터를 아주 잘 설명하고 있다고 볼 수 있다.

3. 두 번째 그래프 (Dataset II) 분석

두 번째 이미지의 데이터는 첫 번째와 완전히 다르다.

  • 특징: 점들이 직선을 따라가는 게 아니라 매끄러운 곡선(무지개 형태) 모양을 하고 있다.
  • 의미: 실제 데이터는 곡선 형태의 규칙을 가지고 있는데, 컴퓨터에게 "직선으로 그려봐"라고 시키니 억지로 직선을 그어놓은 상태다. 이 직선은 데이터의 실제 흐름을 제대로 반영하지 못한다.
import seaborn as sns

anscombe = sns.load_dataset("anscombe")

print(anscombe.head())

sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'I'"),

ci=None, scatter_kws={"s": 80})|

sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'II'"),

ci=None, scatter_kws={"s": 80})

 

앤스콤의 4분할

import seaborn as sns

anscombe = sns.load_dataset("anscombe")
sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'II'"),
order=2, ci=None, scatter_kws={"s": 80})

sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'III'"),
ci=None, scatter_kws={"s": 80})

sns.lmplot(x="x", y="y", data=anscombe.query("dataset == 'III'"),
robust=True, ci=None, scatter_kws={"s": 80})

1. 첫 번째 그래프: 비선형 관계 (곡선 데이터)

이 그래프는 데이터가 직선이 아니라 예쁜 곡선(포물선) 형태를 띠고 있다.

  • 상황: 데이터가 $x$가 커짐에 따라 같이 커지다가 어느 지점부터 다시 작아지는 명확한 규칙을 가지고 있다.
  • 문제점: 만약 이 데이터에 단순히 직선(1차 함수)을 긋는다면, 데이터의 진짜 특징인 '굽어짐'을 전혀 설명하지 못한다.
  • 코드의 의미: order=2라는 옵션은 "이건 직선이 아니라 곡선(2차 함수)으로 그려줘"라고 명령한 것이다. 그래서 그래프를 보면 점들을 아주 정확하게 통과하는 곡선이 그려져 있다.

2. 두 번째 그래프: 이상치(Outlier)의 방해

이 그래프는 거의 모든 점이 일직선 위에 있는데, 딱 하나만 저 멀리 위쪽($x=13$ 부근)에 떨어져 있다.

  • 상황: 대다수의 점은 착하게 직선을 따르지만, 단 하나의 '튀는 값(이상치)'이 존재한다.
  • 결과: 일반적인 선형 회귀(직선 그리기)를 사용하면, 저 멀리 떨어진 점 하나를 포함시키기 위해 직선이 원래 있어야 할 자리보다 위로 붕 떠버린다. 결국 나머지 대다수의 점과도 맞지 않는 어중간한 선이 된다.

3. 세 번째 그래프: 로버스트 회귀 (이상치 무시하기)

첫 번째 그래프와 데이터는 같지만, 그어진 선의 위치가 다르다.

  • 상황: "저 튀는 놈 하나 때문에 전체 흐름을 망칠 순 없어!"라고 판단한 경우다.
  • 코드의 의미: robust=True 옵션을 줬다. 이건 **"상식 밖으로 튀는 놈(이상치)의 영향력을 확 줄여서, 대다수 데이터가 보여주는 흐름에 집중해서 선을 그려라"**라는 뜻이다.
  • 결과: 그래프를 보면 선이 저 멀리 떨어진 점을 무시하고, 일직선상에 있는 점들을 정확하게 관통하고 있다. 훨씬 합리적인 분석이라고 볼 수 있다.

flights 데이터셋(1949년~1960년 항공 승객 수)을 활용해 시간에 따른 데이터의 변화를 분석

import seaborn as sns

# seaborn에서 제공하는 flights 데이터 셋을 로딩함
flights = sns.load_dataset('flights')
flights.shape  # 데이터의 형상을 살펴보자
flights.head()

plt.figure(figsize=(10, 3))
sns.relplot(data=flights, x="year", y="passengers")

plt.figure(figsize=(10, 3))
sns.relplot(data=flights, x="year", y="passengers", kind="line")

1. 첫 번째 그래프: 산점도 (Scatter Plot)

sns.relplot(data=flights, x="year", y="passengers")를 실행했을 때 나오는 결과다.

  • 개별 데이터 표시: 각 연도마다 점이 여러 개(12개) 찍혀 있다. 이는 각 연도의 1월부터 12월까지의 월별 승객 수를 각각 점으로 나타낸 것이다.
  • 분포 확인: 연도가 지날수록 점들이 점점 위로 올라가는 것을 볼 수 있다. 전체적인 승객 수가 매년 증가했다는 사실을 알 수 있다.
  • 편차 확인: 뒤로 갈수록 같은 연도 내에서도 점들 사이의 간격(가장 높은 점과 낮은 점의 차이)이 벌어진다. 이는 시간이 흐를수록 성수기와 비성수기의 승객 차이가 더 커졌음을 의미한다.

2. 두 번째 그래프: 선 그래프 (Line Plot)

kind="line" 옵션을 추가한 결과로, 흩어진 점들을 요약해서 보여준다.

  • 평균선 (중앙의 짙은 선): 각 연도에 해당하는 12개 월의 승객 수를 평균 내어 선으로 이은 것이다. 전체적인 흐름을 한눈에 파악하기 좋다.
  • 신뢰구간 (주변의 흐름한 그림자): 통계적으로 이 정도 범위 내에 데이터가 존재할 확률이 높다는 것을 보여준다. Seaborn은 기본적으로 95% 신뢰구간을 계산해 그림자로 표시한다.
  • 오차의 확대: 연도가 지날수록 그림자의 폭이 넓어지는 것을 볼 수 있다. 이는 앞서 산점도에서 본 것처럼 월별 변동 폭이 커졌기 때문에 통계적인 불확실성이나 변동성도 함께 커졌음을 나타낸다.
분석 항목 특징 의미
추세 (Trend) 꾸준한 우상향 항공 산업이 매년 지속적으로 성장함.
변동성 (Variance) 뒤로 갈수록 커짐 계절에 따른 승객 수 차이가 갈수록 뚜렷해짐.
데이터 요약 평균과 신뢰구간 복잡한 144개의 데이터를 하나의 선과 면으로 단순화하여 가독성을 높임.

'머신러닝' 카테고리의 다른 글

머신러닝 - 선형 회귀 기초  (0) 2026.01.09
PANDAS  (0) 2026.01.08
MATPLOTLIB  (0) 2026.01.07
넘파이(NumPy) 2  (0) 2026.01.07
넘파이(NumPy) 1  (0) 2026.01.06