iBetter Books
수정

DataFrame 직접 연동

"Seaborn 함수 쓸 때 매번 df['열이름'] 이렇게 꺼내야 해요?" 민서가 물었습니다.

선배가 고개를 저었습니다. "아니야. data=df 하고 x='열이름' 하면 끝이야. Seaborn이 알아서 꺼내줘."

data 파라미터의 힘

Seaborn의 모든 함수는 data 파라미터에 Pandas DataFrame을 받습니다. 그리고 x, y, hue 같은 파라미터에는 열 이름을 문자열로 전달하면 됩니다.

import seaborn as snsimport matplotlib.pyplot as pltimport pandas as pd# 샘플 데이터df = sns.load_dataset("tips")# 열 이름만 문자열로 전달하면 끝sns.scatterplot(data=df, x="total_bill", y="tip", hue="sex")plt.title("청구 금액과 팁의 관계")plt.show()

실행 결과

이 방식의 장점은 단순히 편리함만이 아닙니다. Seaborn이 DataFrame의 열 이름을 축 레이블로 자동으로 사용하기 때문에, 별도로 xlabel, ylabel을 설정하지 않아도 의미 있는 레이블이 붙습니다.

tidy data란 무엇인가

Seaborn은 tidy data(정돈된 데이터) 형태를 선호합니다. tidy data의 규칙은 간단합니다.

  • 한 행은 하나의 관측값을 나타냅니다.
  • 한 열은 하나의 변수를 나타냅니다.
  • 하나의 표는 하나의 관측 단위를 나타냅니다.

예를 들어 학생별 과목 점수를 기록할 때, wide-form과 long-form(tidy) 두 가지 방식이 있습니다.

wide-form (비선호):

학생 수학 영어 과학
민서 85 92 78
지호 90 88 95

long-form / tidy data (선호):

학생 과목 점수
민서 수학 85
민서 영어 92
민서 과학 78
지호 수학 90
... ... ...

Seaborn에서 hue, col, row 같은 그룹핑 기능을 쓰려면 long-form이 훨씬 자연스럽습니다. wide-form에서는 "어떤 열이 어떤 변수인지" Seaborn이 파악하기 어렵기 때문입니다.

pd.melt()로 wide → long 변환

현실에서 데이터는 종종 wide-form으로 주어집니다. 엑셀에서 만든 표나 보고서 형식의 데이터가 대표적입니다. 이럴 때 pd.melt()를 사용해 long-form으로 변환합니다.

import pandas as pd# wide-form 데이터wide_df = pd.DataFrame({    "학생": ["민서", "지호", "수연"],    "수학": [85, 90, 88],    "영어": [92, 88, 95],    "과학": [78, 95, 82]})print("wide-form:")print(wide_df)# pd.melt()로 long-form으로 변환# id_vars: 그대로 유지할 열# var_name: 기존 열 이름들이 들어갈 새 열의 이름# value_name: 값들이 들어갈 새 열의 이름long_df = pd.melt(    wide_df,    id_vars=["학생"],    var_name="과목",    value_name="점수")print("\nlong-form (tidy):")print(long_df)

iris 데이터로 변환 실습

실제로 wide-form 데이터를 long-form으로 변환하고 시각화해보겠습니다. iris 데이터셋은 꽃잎과 꽃받침의 길이/너비가 각각 별도 열로 구성된 wide-form입니다.

import seaborn as snsimport matplotlib.pyplot as pltimport pandas as pd# iris 데이터 로드iris = sns.load_dataset("iris")print("원본 iris 데이터 (wide-form):")print(iris.head())print(f"\n크기: {iris.shape}")# wide → long 변환# species 열은 그대로 유지하고, 나머지 수치 열들을 녹임iris_long = pd.melt(    iris,    id_vars=["species"],    var_name="measurement",    value_name="value")print("\n변환 후 (long-form):")print(iris_long.head(8))print(f"크기: {iris_long.shape}")# wide-form으로는 하나의 boxplot에 4가지 측정값을 한번에 비교하기 어려움# long-form이면 x='measurement', y='value', hue='species'로 바로 시각화 가능fig, axes = plt.subplots(1, 2, figsize=(14, 5))# wide-form: 하나의 변수만 시각화 가능sns.boxplot(data=iris, x="species", y="sepal_length", ax=axes[0])axes[0].set_title("wide-form: 꽃받침 길이만 비교")axes[0].set_xlabel("품종")axes[0].set_ylabel("길이 (cm)")# long-form: 모든 측정값을 한번에 비교sns.boxplot(data=iris_long, x="measurement", y="value", hue="species", ax=axes[1])axes[1].set_title("long-form: 모든 측정값 비교")axes[1].set_xlabel("측정 항목")axes[1].set_ylabel("값 (cm)")axes[1].tick_params(axis='x', rotation=15)axes[1].legend(title="품종", bbox_to_anchor=(1.05, 1), loc='upper left')plt.tight_layout()plt.show()

실행 결과

오른쪽 차트를 보면, long-form으로 변환한 덕분에 4가지 측정값을 3가지 품종과 함께 한 번에 비교할 수 있습니다. wide-form으로는 이런 시각화를 만들기 위해 훨씬 복잡한 코드가 필요했을 것입니다.

핵심 정리

  • Seaborn 함수의 data 파라미터에 DataFrame을 넣고, x, y, hue에 열 이름(문자열)을 전달합니다.
  • tidy data는 "한 행 = 한 관측, 한 열 = 한 변수" 원칙을 따릅니다.
  • wide-form 데이터는 pd.melt(id_vars, var_name, value_name)으로 long-form으로 변환합니다.
  • long-form 데이터는 Seaborn의 hue, col, row 기능을 최대한 활용할 수 있게 해줍니다.