pip install seaborn==0.11import seaborn as sns
sns.countplot(data=student)

sns.countplot(x = "race/ethnicity", data=student) # Case 1
sns.countplot(y = "race/ethnicity", data=student) # Case 2
"""
x 파라미터나 y 파라미터를 통해 내가 원하는 Feature를 선택한다
Case 1 : x축을 race/ethnicity Feature 값으로 설정하여 countplot을 그린다
Case 2 : y축을 race/ethinicty Feature 값으로 설정하여 countplot을 그린다
Case 2를 조금 더 자세히 생각해보면, Horizontal Bar Plot임을 알 수 있다
(y축이 Feature, 즉 범주)
아래 그림에서 왼쪽 차트가 Case 1, 오른쪽 차트가 Case 2
"""

sns.countplot(order = sorted(student['race/ethnicity'].unique()),
data=student, x = "race/ethnicity")
"""
order Parameter를 통해 내가 설정한 축에 대해 Order가 가능하다
sorted() 메서드를 활용했으므로, race/ethinicity Feature의 오름차순으로
그래프를 그림을 알 수 있다
아래 차트에서, group A -> group E 순으로 출력 되는 것을 볼 수 있다
"""

sns.countplot(hue = "gender", data=student, x = "race/ethnicity",
order = sorted(student['race/ethnicity'].unique()))
"""
hue Parameter를 통해 내가 원하는 Feature로 Group을 생성하여
Grouped Bar Plot을 생성할 수 있다
위 코드를 보면 hue = "gender"로 지정하였다.
즉, 성별으로 Group을 나눠 그래프를 그리는 것이다
아래 사진을 보면 결과적으로 gender에 저장된 "female", "male"로 Bar가
나눠짐을 볼 수 있다
"""

fig, ax = plt.subplots(1,2,figsize=(12,7))
# Case 1 : palette Parameter 활용
sns.countplot(ax = ax[0], palette="Set2",
hue_order=sorted(student['race/ethnicity'].unique()),
hue = "race/ethnicity",data=student, x = "gender")
# Case 2 : color Parameter 활용
sns.countplot(ax = ax[1], color="red",
hue_order=sorted(student['race/ethnicity'].unique()),
hue = "race/ethnicity",data=student, x = "gender")
"""
Case 1이 왼쪽 차트, Case 2가 오른쪽 차트임을 알고 가자
Case 1같은 경우 ax = ax[0], Case 2 같은 경우 ax[1]이므로
Case 1이 왼쪽, Case 2가 오른쪽에 그려진 것이다
"""

fig, ax = plt.subplots(2,1, figsize= (12, 12))
sns.boxplot(x="math score", data = student, ax = ax[0])
# 기본 boxplot 그리는 방식.
# x 위치에 "어떤 Data의 통계치"로 Plot을 그릴지 결정해 줘야 함
# x Feature 기준으로 25%, 50%, 75% Data를 뽑고, 이를 활용해 그림
# ===========================================================#
sns.boxplot(x="race/ethnicity", y = "math score",
data = student, ax = ax[1])
# box plot에서 x와 y에 Feature를 모두 입력
# Math score에 대해 25%, 50%, 75% 값을 구하는 것 자체는 동일하지만,
# 이 값을 x Feature로 Group을 나눈 뒤 만든다
# 즉, x라는 Feature로 Group을 나눈 뒤 데이터를 뽑아 Box Plot을 그리는 것이다
# ===========================================================#
sns.boxplot(width=0.3, linewidth=2, fliersize=10,x="race/ethnicity",
y = "math score", data = student, ax = ax[2])
# ax[1] 차트에서 width, linewidth, fliersize만 변경하였다
# ax[2] 차트를 보면, width는 줄어들었으며, 라인의 두께는 두꺼워졌고,
# 예외치의 그림(다이아몬드) 크기는 커졌음을 볼 수 있다
plt.show()

<이유>
이산 데이터는 연속적이지 않기 때문에 중간 데이터가 존재하지 않는데,
Violine Plot을 활용하면 데이터 범위가 없는 곳까지 데이터가 있다고 표시하여
사용자가 해당 부분에 데이터가 존재한다고 착각할 수도 있다.
또한 Kernel Density Estimate를 활용하므로, Kernel의 모양에 따라
데이터의 손실이나 오차가 발생할 수 있음
sns.violinplot(x='math score', data=student)
# x 위치에 "어떤 Data의 통계치"로 Plot을 그릴지 결정해 줘야 함
# 이 경우, math score의 통계치로 그래프를 그릴 것임

sns.violinplot(x='math score', data=student,
bw = 0.1)

<설명>
Violin Plot은 양쪽 끝이 한 점으로 수렴하는 그래프로써, 실제 데이터와 차이가 있다
예를 들어, 위 Violin Plot을 보면 Math score의 Max값은 100이지만,
그래프가 오른쪽 끝 점에서 만나야 하기 때문에 어쩔 수 없이 100을 넘어서도
(그래프의) 값이 존재하는 것을 볼 수 있고, 이를 보는 User는 실제로 100점이 넘는
점수가 존재한다고 오해를 할 수 있다.
아래 예시에서는 cut = 0이므로, Data의 Max값과 Min값에서 그래프를 추가로
그리는 것을 허락하지 않았다
따라서, Max값과 Min 값을 정확히 지키는 Violin Plot이 그려질 것이다
(잘라진 것처럼 보임)
sns.violinplot(x='math score', data=student,
cut = 0)

sns.violinplot(x='math score', data=student, inner='stick', ax = ax[0])
sns.violinplot(x='math score', data=student, inner='quartile',ax = ax[1])

sns.violinplot(x='race/ethnicity', y = 'math score', data=student,
ax = ax[0], scale = "count")
sns.violinplot(x='race/ethnicity', y = 'math score', data=student,
ax = ax[1], scale="width")
sns.violinplot(x='race/ethnicity', y = 'math score', data=student,
ax = ax[2], scale="area")

<설명>
위에서 Violin Plot을 그리면서 가운데 라인을 기준으로 좌우가 같다는 것을 알 수 있다
즉, 가운데 라인을 기준으로 한 쪽 Part에 대한 Plot만 존재해도
Data 파악에 문제가 없다는 의미이다
만약, Hue를 통해 데이터 Group이 2개로 쪼개진다면, 2개 Group에 대한
Violin Plot을 반씩 쪼개서 붙여 한 개 Violin Plot으로 만들어 줄 수 있지 않을까?
"split = True"로 설정할 경우 이런 방법으로 Violin Plot을 구현해준다
1개의 Line에 hue로 생성된 group의 Violin Plot 절반 씩을 표현하게 하는 것이다
아래 코드에서는 "gender"로 gorup을 나눴고,
gender는 "female", "male" 밖에 존재하지 않으므로
2개 Violin Plot을 반으로 쪼개 1개 라인에 붙여 표현했다
sns.violinplot(x='race/ethnicity', y = 'math score', data=student,
hue = 'gender', split = True)

fig, axes = plt.subplots(3,1, figsize=(12, 15))
sns.boxenplot(x='math score', data=student, ax=axes[0],
order=sorted(student['race/ethnicity'].unique()))
sns.swarmplot(x='math score', data=student, ax=axes[1],
order=sorted(student['race/ethnicity'].unique()))
sns.stripplot(x='math score', data=student, ax=axes[2],
order=sorted(student['race/ethnicity'].unique()))
axes[0].set_title("boxenplot", loc = "left")
axes[1].set_title("swarmplot", loc = "left")
axes[2].set_title("stripplot", loc = "left")
plt.show()

sns.histplot(x='math score', data= student)
# Categorial API와는 달리 Distribution API는
# 통계치를 구하지 못하는 Feature여도 x, y로 입력이 가능함

sns.histplot(binwidth=10, x='math score', data= student, ax = ax[0])
sns.histplot(bins = 25,x='math score', data= student, ax = ax[1])

sns.histplot(element='step',x='math score', data= student, ax = ax[0])
sns.histplot(element='poly',x='math score', data= student, ax = ax[1])


fill=True Parameter 설정을 활용하여 가시성 높이는 것을 추천sns.kdeplot(x= 'math score', data=student, ax = ax[0])
sns.kdeplot(fill = True, x= 'math score', data=student, ax = ax[1])
# fill = True로 가시성을 높이자(오른쪽 그림)

sns.kdeplot(bw_method = 0.05, x= 'math score', data=student, fill = True)

sns.kdeplot(cumulative = True, x='math score', data=student, fill = True)
# 결과를 보면 Density가 최종 지점의 y값이 1이 됨을 알 수 있다.
# 이전 Data 값들까지 현재 Data에 포함 시켜 밀도를 계산하기 때문에,
# 최종적인 지점에서 밀도는 모든 Data를 포함했다는 의미를 지닌 1.0 값을 가진다

sns.ecdfplot(x = 'math score', data=student, ax=ax[0])
sns.rugplot(x = 'math score', data=student, ax=ax[1])
# 위 차트가 ecdfplot, 아래 차트가 rugplot

Bivariate Distribution
sns.histplot(x = 'math score', y = 'reading score',
data = student,
cbar = True,
bins = (20,20))
<설명>
x축에는 math score, y축에는 reading score Feature가 설정되어 있다
Bivariate Distribution은 2개 값이 겹치는 Data의 Count를 나타내는 것이다
예를 들어, math score = 60, reading score = 80일 경우,
(60, 80) Point에 존재하는 Histogram을 확인하면 된다.
또한, 오른쪽 color bar를 통해 해당 Point의 점수를 가진 사람 수를 알 수 있다
cbar = True : color bar 활성화
bins : Data를 몇 개씩 묶어 차트로 표현할 것인가(위에 설명한 bins와 동일)
(x bins, y bins) 쌍으로 입력함

sns.kdeplot(x = 'math score', y = 'reading score', data = student, fill=True)

아래 예시 코드는 size, style, hue를 모두 활용할 수 있다는 것을 보여주기 위해
모든 Parameter를 활용했지만, 가시성이 매우 떨어지므로 실제로 활용할 때는
3개 Parameter 중 가장 가시성이 좋은 Grouping 방식으로 Feature를 전달해야 함
sns.scatterplot(x='math score', y='reading score', data = student,
style = 'gender', markers={'male':'s', 'female':'o'},
hue = 'race/ethnicity',
hue_order=sorted(student['race/ethnicity'].unique()),
size = 'writing score')
"""
style : male을 s(사각형), female을 o(원) 모양으로 Marker를 변경 후
Scatter plot에 표현
hue : race/ethnicity를 기준으로 색을 다르게 하여 scatter plot에 표현
size : writing score의 값(점수)에 따라 Marker의 크기를 다르게 하여
Scatter Plot에 표현
"""

sns.regplot(x='math score', y='reading score', data=student, ax = ax[0][0])
sns.regplot(x_estimator=np.mean, x='math score', y='reading score',
data=student, ax = ax[0][1])
sns.regplot(order=4, x='math score', y='writing score', data=student,
ax = ax[1][0])
sns.regplot(logx = True, x='reading score', y='writing score',
data=student, ax = ax[1][1])
"""
그래프에 왼쪽 상단에 나온 Title이 값을 준 Parameter이다
Quadratic, 즉 order=4로 줬을 경우 4차 방정식으로 안보이겠지만 데이터가
너무 선형에 가까워서 그렇게 보이는 것이다
x_estimator를 np.mean으로 했으므로, 한 개 축에 대하여 1개 포인트
(축에 존재하는 모든 데이터 평균)만 존재하고, 직선으로 데이터 Range를 보여준다
"""

sns.lineplot(data=student, x='race/ethnicity',y='math score',
hue = 'gender')
"""
새로운 Data Set을 가져오기가 귀찮아 Student를 활용했지만, 제대로 활용하기 위해서는
시간 흐름에 연관된 시계열 데이터로 Line Plot을 그리는 것이 더 효과적이다
student는 시계열 데이터가 아니므로, Line Plot의 모든 기능을 끌어내기 어렵다
"""

fmt='.2f'와 같이 표현할 Data의 소수 자릿수 제한까지 가능함sns.heatmap(student.corr(),
vmin = -1, vmax = 1,
center = 0,
cmap = 'coolwarm',
annot=True, fmt='.2f',
ax = ax[0])
sns.heatmap(student.corr(),
vmin = -1, vmax = 1,
center = 0,
cmap = 'coolwarm',
annot=True, fmt='.2f',
ax = ax[1], linewidth = 2.0)
<설명>
먼저, student DataFrame이 Correlation이 너무 좋아서 사실 보여주기 좋은
DataSet은 아니다
먼저, correlation 값은 -1 ~ 1 사이의 값을 가진다. 따라서, 해당 Range를
벗어나는 값에 대하여 색을 지정해 줄 필요는 없을 것이다
따라서, vmin = -1, vmax = 1로써 최대, 최솟값을 지정하여 색을 할당해 줄 Range를
정해준다
또한 Correlation은 0 값을 기준으로 양의 상관관계, 음의 상관관계가 구분되므로
center = 0으로 지정했다
(cmap은 color 지정이므로 생략하겠다)
annot = True를 통해 Correlation 값을 matrix에 표기하였다.
fmt = '.2f'로 설정했으므로, 소수점 아래 2자릿수 까지 표현될 것이다
마지막으로 똑같은 그래프인데 오른쪽 차트는 linewidth를 2.0으로 설정하여
Matrix의 칸을 나눴다

<설명>
참고로, 위의 Correlation 같은 경우 대각 성분을 기준으로 위아래가 대칭임을
알 수 있다.
이는 Correlation 특징이다.
그렇다면, 굳이 사각형의 모든 성분을 다 표현해야 할까? 그냥 아래나 위 요소만
표현하면 되지 않을까?
또한, 대각 행렬의 값 같은 경우 당연히 1 값을 가질텐데 생략할 수는 없을까?
(같은 Feature 끼리는 corr 값은 무조건 1)
아래 코드를 통해 구현할 수 있다.
mask = np.zeros_like(student.corr()) # corr과 같은 크기로 0 행렬 만듦
mask[np.triu_indices_from(mask)] = True
# 만든 0 행렬 중 내가 보여주기를 원하는 위치에만 True 값 설정해줌
sns.heatmap(student.corr(),
vmin = -1, vmax = 1,
center = 0,
cmap = 'coolwarm',
annot=True, fmt='.2f',
mask = mask)
# 위에서 대각 행렬 기준 아래 존재하는 행렬에만 True 값을 넣어줬으므로
# 아래와 같은 그림이 나옴

sns.jointplot(x = 'math score', y = 'reading score', data = student)

fill = True를 통해 가시성 높이기# hue Parameter와 같이 활용할 수 있는 kind
sns.jointplot(x = 'math score', y = 'reading score', data = student,
hue="gender",
kind = "hist")
sns.jointplot(x = 'math score', y = 'reading score', data = student,
hue="gender",
kind = "scatter")
sns.jointplot(x = 'math score', y = 'reading score', data = student,
hue="gender",
kind = "kde", fill = True)

# hue Parameter와 같이 활용할 수 "없는" kind
sns.jointplot(x = 'math score', y = 'reading score', data = student,
kind="hex")
sns.jointplot(x = 'math score', y = 'reading score', data = student,
hue="gender",
kind = "kde", fill = True)

sns.pairplot(data=student, hue = "gender")

fill=True로 가시성 높이기sns.pairplot(data=student, hue = "gender",
kind = "hist", corner = True)
# corner = True로 설정했으므로 대각 성분 아래 Subplot들만 출력함

sns.catplot(x='math score', y='writing score', data=student,
hue = "gender", col="test preparation course", row = "lunch")
<설명>
col을 test preparation course, row를 lunch feature로 설정하였다.
즉, col(Column)이 바뀔 때마다 test preparation course 값을 바꿔서
그래프를 그려볼 것이며 row(Row)가 바뀔 때마다 lunch 값을 바꿔 그래프를
그려볼 것이다
아래 그래프를 보면 알겠지만, [0,0]위치와 [0,1] 위치 그래프 위에
test preparation course 값이 바뀌었음을 볼 수 있다.
즉, (lunch, test preparation course)에 해당하는 Data에 대해서만
그래프를 그린 것이다
반대로, [0,0] 위치와 [1,0] 위치 그래프를 보면 row가 바뀌었으므로
lunch 값이 바뀌었음을 볼 수 있다
