Python/Study

[Python / Study] Seaborn tips 내장 데이터를 이용해 시각화하기

Sukyung Jang 2023. 4. 16. 18:54

1. 라이브러리 설치 및 데이터 불러오기


import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset('tips')
tips.head()

pandas, matplotlib.pyplot과 seaborn을 import 합니다.

그 다음 load.dateset() 함수로 tips 데이터를 불러와 tips 변수에 저장합니다.

  • 출력

tips.head()로 데이터를 5줄만 불러왔습니다.

  • 컬럼 설명

- total_bill : 총 계산 요금 (달러)

- tip : 팁 (달러)

- sex : 성별

- smoker : 흡연 여부

- day : 요일

- time : 식사 시간

- size : 식사 인원

 

2. 데이터 그룹화하기


tips_day = tips.groupby("day").mean().reset_index() # day 그룹
display(tips_day)
tips_sex = tips.groupby("sex").mean().reset_index() # sex 그룹
display(tips_sex)
tips_smoker = tips.groupby("smoker").mean().reset_index() # smoker 그룹
display(tips_smoker)
tips_size = tips.groupby("size").mean().reset_index() # size 그룹
display(tips_size)

day, sex, smoker, size를 그룹화하여 평균을 내서 각 변수에 저장했습니다.

 

  • 요약

- groupby() : 해당 컬럼으로 그룹화합니다.

- mean() : 해당 컬럼에 대한 평균을 계산합니다.

- reset_index() : 데이터프레임의 인덱스를 다시 설정합니다.

 

  • 출력 예시

저는 print() 대신 display() 함수를 사용하여 출력했습니다.

print() 함수를 사용하면 텍스트만 나와서 보기 힘들다는 느낌이 들어서 display() 함수를 사용했습니다.

 

3. 시각화 함수 생성


  • 요일별 평균 함수
# 요일별 평균
def plot_day(ax, zorder = 0):
    # tips_day["day"] : x축, tips_day["tip"] : y축, color : 회색
    # zorder는 막대의 x 좌표를 고정하는 매개변수
    ax.bar(tips_day["day"], tips_day["tip"], color = "lightgray", zorder = zorder)

    # 차트의 제목을 설정하는 코드
    # pad는 제목, 레이블 등과 같은 텍스트 요소와 축 간격을 조절하는 매개변수
    # pad = 12 는 제목과 그림의 상단 경계 간의 간격을 12 포인트로 설정
    ax.set_title("Day Mean", fontsize = 16, pad = 12, fontweight = 'bold')
    ax.title.set_color('red')
    ax.title.set_fontname('Arial')

    ax.set_xticks(tips_day.index) # ax.set_xticks 메소드는 x축의 눈금 위치를 설정하는 메소드
    ax.set_xticklabels(["Thur", "Fri", "Set", "Sun"], fontsize=16, fontweight = 'bold') # x 레이블 지정
    
    # 막대 차트 상단에 해당 막대의 값을 나타내는 텍스트를 추가하는 부분
    h_pad = 0.1 # 텍스트가 막대 위에 위치할 수 있도록 막대 위쪽으로 간격 설정
    for i in range(4): # 각각의 막대에 대한 반복문
        fontweight = "normal" # 일반적인 텍스트 스타일
        color = "k" # 일반적인 텍스트 스타일
        if i == 3: # 주말에 해당하는 막대 텍스트를 굵게 표시, 빨간색으로 표시
            fontweight = "bold"
            color = "darkred"

        # text()를 사용하여 텍스트 추가
        # i는 x축 좌표값, tips_day["tip"].loc[i] + h_pad, y축 좌표값
        # f"{tips_day['tip'].loc[i]:0.2f}" : 소수점 이하 2자리까지 반올림하여 막대의 값을 나타냄
        # horizontalalignment = 'center' : 텍스트를 정렬하는 매개변수, 가로 정렬 방식 (center, left, right)
        ax.text(i, tips_day["tip"].loc[i] + h_pad, f"{tips_day['tip'].loc[i]:0.2f}",
                horizontalalignment = 'center', fontsize = 12, fontweight = fontweight, color = color)
    
    # patch : 모양과 색상을 가지는 2차원 도형을 나타내는 객체, patches : patch를 담고 있는 리스트
    # facecolor : patch 객체의 색상을 darkred, edgecolor : 테두리 색상을 black
    ax.patches[3].set_facecolor("darkred")
    ax.patches[3].set_edgecolor("black")

    # ylim : y축 범위를 설정, y축 범위를 고정
    # y축의 범위를 자동으로 조정해야 할 경우엔 ax.autoscale() 메소드 사용
    ax.set_ylim(0, 4)
    return ax

공부하면서 배운 것을 주석으로 해당 함수와 파라미터에 대한 설명을 넣었습니다.

이 함수는 요일별 평균을 낸 것을 시각화하기 위한 함수입니다.

 

  • 성별에 따른 평균
def plot_sex(ax, zorder = 0):
    ax.bar(tips_sex["sex"], tips_sex["tip"], color = "lightgray", zorder = zorder)
    
    ax.set_title("Gender Mean", fontsize = 16, pad = 12, fontweight = 'bold')
    ax.title.set_color('blue')
    ax.title.set_fontname('Arial')

    ax.set_xticks(tips_smoker.index)
    ax.set_xticklabels(["Male", "Female"], fontsize=16, fontweight = 'bold')
    
    h_pad = 0.1
    for i in range(2):
        fontweight = "normal"
        color = "k"
        if i == 0:
            fontweight = "bold"
            color = "darkblue"

        ax.text(i, tips_sex["tip"].loc[i] + h_pad, f"{tips_sex['tip'].loc[i]:0.2f}",
                horizontalalignment = 'center', fontsize = 16, fontweight = fontweight, color = color)
    
    ax.patches[0].set_facecolor("darkblue")
    ax.patches[0].set_edgecolor("black")

    ax.set_ylim(0, 4)
    return ax

성별에 따른 평균을 구하기 위한 함수입니다.

 

  • 흡연 여부에 따른 평균
# 흡연자 비흡연자
def plot_smoker(ax, zorder=0):
    ax.bar(tips_smoker["smoker"], tips_smoker["tip"], color="lightgray", zorder=zorder, label='tip')

    ax.set_title("Smoker Mean", fontsize=16, pad=12, fontweight = 'bold')
    ax.title.set_color('green')
    ax.title.set_fontname('Arial')

    ax.set_xticks(tips_smoker.index)
    ax.set_xticklabels(["Smoke", "No Smoke"], fontsize=16, fontweight = 'bold')
    
    h_pad = 0.1
    for i in range(2):
        fontweight = "normal"
        color = "k"
        if i == 0:
            fontweight = "bold"
            color = "green"

        ax.text(i, tips_smoker["tip"].loc[i] + h_pad, f"{tips_smoker['tip'].loc[i]: .2f}",
                horizontalalignment='center', fontsize=16, fontweight=fontweight, color=color)


    ax.patches[0].set_facecolor("green")
    ax.patches[0].set_edgecolor("black")

    ax.set_ylim(0, 4)
    return ax

흡연 여부에 따른 평균입니다.

 

  • 식사 인원에 따른 평균
# 식사 인원에 따른 평균
def plot_size(ax, zorder=0):
	# 선 차트
    width = 0.4
    ax.plot(tips_size["size"], tips_size["tip"], color="skyblue", zorder=zorder, marker = 'D', ms = 10, label="Tip", linewidth=4) # 팁
    ax.plot(tips_size["size"], tips_size["total_bill"], color="blue", zorder=zorder, marker = 'D', ms = 10, label="Total Bill", linewidth=4) # 총 계산 요금
    # Marker : diamond, markersize : 10, linewidth : 4

    ax.set_title("Size Mean", fontsize=16, pad=12, fontweight = 'bold')
    ax.title.set_color('orange')
    ax.title.set_fontname('Arial')
    
    ax.set_xticks(tips_size.index + 1)
    ax.set_xticklabels(["One", "Two", "Three", "Four", "Five", "Six"], fontsize=16, fontweight = 'bold')

    # value
    h_pad = 2
    for i in range(6):
        fontweight = "bold"
        color = "k"
        if i == 5:
            fontweight = "bold"
            color = "red"

        ax.text(i+1-width/2, tips_size["tip"].loc[i] + h_pad, f"{tips_size['tip'].loc[i]: .2f}",
                horizontalalignment='center', fontsize=16, fontweight=fontweight, color=color)

        ax.text(i+0.7+width/2, tips_size["total_bill"].loc[i] + h_pad , f"{tips_size['total_bill'].loc[i]: .2f}",
                horizontalalignment='center', fontsize=16, fontweight=fontweight, color=color)

    # Marker
    ax.plot(6, tips_size.loc[5, "tip"], marker='D', markersize=15, color='red')
    ax.plot(6, tips_size.loc[5, "total_bill"], marker='D', markersize=15, color='red')

    # set_range
    ax.set_ylim(0, 40)
    return ax

식사 인원에 따른 평균입니다.

식사 인원 시각화는 선 차트가 좋을 것 같아서 선 차트로 시각화했습니다.

팁에 관한 선 차트와 총 계산 금액 선 차트, 2개의 차트를 넣었습니다.

 

4. 시각화


시각화 코드

fig, ax = plt.subplots(nrows = 2, ncols = 2, figsize=(15, 10))
ax[0, 0] = plot_day(ax[0, 0], zorder = 2) # 요일별 평균
ax[0, 1] = plot_sex(ax[0, 1], zorder = 2) # 성별에 따른 평균
ax[1, 0] = plot_smoker(ax[1, 0], zorder = 2) # 흡연 여부에 따른 평균
ax[1, 1] = plot_size(ax[1, 1], zorder = 2) # 식사 인원에 따른 평균

# 윤곽선 제거
ax[0, 0].spines["top"].set_visible(False)
ax[0, 0].spines["right"].set_visible(False)
ax[0, 1].spines["top"].set_visible(False)
ax[0, 1].spines["right"].set_visible(False)
ax[1, 0].spines["top"].set_visible(False)
ax[1, 0].spines["right"].set_visible(False)
ax[1, 1].spines["top"].set_visible(False)
ax[1, 1].spines["right"].set_visible(False)

# 식사 인원에 따른 평균 차트에서 화살표 마크 추가
ax[1, 1].plot(1, 0, ">k", transform=ax[1, 1].get_yaxis_transform(), clip_on=False)

# 왼쪽 윤곽선 밖으로 15 움직임
ax[1, 1].spines["left"].set_position(("outward", 15))

# subplot간의 간격과 축 레이블의 위치를 자동으로 조정
plt.tight_layout()
plt.show()

위의 코드를 사용하여 시각화를 하였습니다.

 

  • 출력

시각화 한 모습입니다.

 

지금까지 tips 데이터를 이용하여 시각화를 연습해봤습니다.

제가 공부하는 과정을 기록하는 글입니다.