플롯과 데이터 구조
일반적으로 플롯은 지정된 x와 y에 대응하여 작성됩니다. 각 x와 y를 위해 seaborn 함수에 전달하는 데이터 구조에 따라 입력 형식에서 약간의 차이를 보입니다. DataFrame의 경우 모든 변수들이 열(column)로 배치되고 각 열이름이 하나의 변수를 나타내는 구조이기 때문에 x와 y에 열이름을 전달합니다. 그러나 행과 열이 연결되어 각 값들의 의미를 나타내는 경우 즉, pivot table과 같은 경우 x와 y는 각각 행이름이고 열이름이 됩니다. 이 경우 그래프 함수는 각 행에 대한 열을 x와 y를 암묵적으로 인식하여 그래프를 작성합니다. 이러한 관계를 다음 데이터 flight에 대해 figure-level 함수인 relplot(), catplot()
를 적용하여 알아봅니다(Figure-level과 Axes-level 함수 그리고 히스토그램 참조).
import numpy as np import pandas as pd import matplotlib.pyplot as plt plt.rcParams['font.family'] ='NanumGothic' plt.rcParams['axes.unicode_minus'] =False import seaborn as sns
flights=sns.load_dataset("flights") flights.head(3)
year | month | passengers | |
---|---|---|---|
0 | 1949 | Jan | 112 |
1 | 1949 | Feb | 118 |
2 | 1949 | Mar | 132 |
sns.set_theme() sns.relplot(data=flights, x="year", y="passengers", hue="month", kind="line" ) plt.show()
위 데이터 flights는 각 변수가 열(column)으로 정렬되어 있는 구조인데 반해 다음과 같이 pivot_table인 경우를 그래프로 나타내기 위해서는 각 행의 이름과 각 열의 이름을 다른 축에 배치되어야 하는 구조입니다. 이 경우는 x, y를 지정할 수 없는 대신 seaborn 함수 자체에서 암묵적으로 x와 y축에 각 행이름과 열이름으로 자동 매칭됩니다. 그러므로 인위적으로 x, y를 지정할 수 없습니다.
flight_pivot=flights.pivot(index="month", columns="year", values="passengers") flight_pivot.head(3)
year | 1949 | 1950 | 1951 | 1952 | 1953 | 1954 | 1955 | 1956 | 1957 | 1958 | 1959 | 1960 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
month | ||||||||||||
Jan | 112 | 115 | 145 | 171 | 196 | 204 | 242 | 284 | 315 | 340 | 360 | 417 |
Feb | 118 | 126 | 150 | 180 | 196 | 188 | 233 | 277 | 301 | 318 | 342 | 391 |
Mar | 132 | 141 | 178 | 193 | 236 | 235 | 267 | 317 | 356 | 362 | 406 | 419 |
sns.relplot(data=flight_pivot, kind="line") plt.show()
다음 그림은 위 데이터를 전치한 것입니다.
sns.relplot(data=flight_pivot.T, kind="line") plt.show()
위 그림의 x는 명목변수입니다. 그러므로 박스형으로 작성할 수 있습니다. 위와 마찬가지로 x,y는 암묵적으로 인식됩니다.
sns.catplot(data=flight_pivot.T, kind="box") plt.show()
다음 데이터의 샘플은 두개의 명목변수에 대응하는 세개의 값이 할당된 구조입니다. 이러한 구조의 데이터를 messy data라하며 pd.melt()
함수 등으로 여러개의 id를 나타내는 명목변수에 대응하는 1개의 값을 할당하는 구조 즉, 정돈된 구조(tidy data)로 변환시킬 수 있습니다.
Messy data의 구조로 여러개의 값을 하나의 플롯으로 나타내기 어렵습니다. 대신에 각 명목변수에 대응하는 값들이 하나의 열로 이루어진 구조로 변환 후 플롯을 작성할 수 있습니다.
anag = sns.load_dataset("anagrams") anag.head(3) #messy data
subidr | attnr | num1 | num2 | num3 | |
---|---|---|---|---|---|
0 | 1 | divided | 2 | 4.0 | 7 |
1 | 2 | divided | 3 | 4.0 | 5 |
2 | 3 | divided | 3 | 5.0 | 6 |
anag_tidy=anag.melt(id_vars=["subidr", "attnr"], var_name="solutions", value_name="score") anag_tidy.head(3) #tidy data
subidr | attnr | solutions | score | |
---|---|---|---|---|
0 | 1 | divided | num1 | 2.0 |
1 | 2 | divided | num1 | 3.0 |
2 | 3 | divided | num1 | 3.0 |
sns.catplot(data=anag_tidy, x="solutions", y="score", hue="attnr", kind="point") plt.show()
sns.catplot(data=anag_tidy, x="solutions", y="score", hue="attnr", kind="box") plt.show()
다음은 표 형식이 아닌 자료 구조에 대한 플롯 작성을 나타낸 것입니다. 사전형식의 자료에서 각 key는 x, y, hue에 전달하는 변수 명이 됩니다.
flight_dict=flights.to_dict() flight_dict.keys()
dict_keys(['year', 'month', 'passengers'])
sns.relplot(data=flight_dict, x="year", y="passengers", hue="month", kind="line") plt.show()
x와 y등의 데이터가 분리된 경우 즉, 플롯함수의 x, y 인수에 별도의 객체를 전달할 경우 인수 data를 사용할 필요가 없습니다. 다음은 flights로 부터 각 year에 대응하는 passengers의 평균을 작성한 것으로 인덱스와 passengers 열을 별도로 분리하여 그래프를 작성해봅니다.
flight_ave=flights.groupby('year').mean(numeric_only=True) flight_ave.head(3)
passengers | |
---|---|
year | |
1949 | 126.666667 |
1950 | 139.666667 |
1951 | 170.166667 |
yr=flight_ave.index passen=flight_ave.passengers sns.relplot(x=yr, y=passen, kind="line") plt.show()
위에서 분리된 객체 yr, passen은 객체의 이름을 포함하고 있기 때문에 x, y의 축 이름이 생성되지만 객체내에 이름이 없을 경우 축이름은 생성되지 않습니다. 다음은 객체 yr, passen을 numpy.array로 변환한 것으로 객체의 이름을 name 속성을 사용하여 별도로 지정해 주지 않은 경우 이름을 포함하지 않습니다. 그러므로 다음과 같이 각 축 레이블의 이름을 나타낼 수 없습니다.
sns.relplot(x=yr.to_numpy(), y=passen.to_list(), kind="line") plt.show()
이 경우 set_axis_labels()
함수를 사용하여 축의 레이블을 첨가할 수 있습니다.
g=sns.relplot(x=yr.to_numpy(), y=passen.to_list(), color="red", kind="line") g.set_axis_labels("year", "passengers") plt.show()
댓글
댓글 쓰기