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를 제공한다.
- relplot() (Relational): 수치형 변수 간의 관계(상관관계)를 그릴 때 사용 (Scatter, Line).
- displot() (Distribution): 데이터가 어디에 분포해 있는지 볼 때 사용 (Histogram, KDE).
- catplot() (Categorical): 범주형 데이터(예: 성별, 품종)의 수치를 비교할 때 사용 (Bar, Box, Violin).
5. 상관관계 vs 인과관계 (Correlation vs Causality)
- 상관관계: 두 변수 x와 y가 같이 움직이는 경향성. 하나가 증가할 때 다른 하나도 증가하거나(양), 감소하는(음) 현상을 말한다.
- 인과관계: 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 |