데이터 시각화

김채윤·2025년 12월 1일

python에서 라이브러리를 이용해 데이터 시각화를 할 수 있다
1. Matplotlib
2. seaborn: Matplot보다 그림이 좀 더 예쁘다
3. Altair: 그래프를 움직일 수 있다
4. PyGWalker: 드래그 앤 드랍으로 간단하게 EDA가 가능하다
5. plotly

기본 그래프 그리기

df2.groupby('Gender')['Customer ID'].count().plot.bar()

그래프에서 색을 마음대로 지정할 수도 있다

df2.groupby('Gender')['Customer ID'].count().plot.bar(color=['yellow','purple'])



옵션을 통해 그래프의 세세한 부분을 수정할 수 있다.
matplotlib.pyplot 내에 있는 subplot모듈을 사용하면 여러 그래프를 동시에 시각화할 수 있다.
4개의 구역을 만들려면
fig.ax=plt.subplots(2,2)를 입력하면
ㅁㅁ
ㅁㅁ
네 개의 그래프가 나오고 각각 (0,0) (0,1) (1,0) (1,1)이 된다.

seaborn을 이용해서 그릴 수 있는 그래프도 다양하다

Altair에서 아래 옵션을 통해 그래프를 그릴 수 있다


d1이 다음과 같을 때 이를 이용해서 시각화를 진행해보자

#matplotlib 라이브러리를 통한 그래프 그리기
# figure 함수를 이용하여, 전체 그래프 사이즈 조정 
dplot1 = plt.figure(figsize = (10 , 3))

# x축, y축 설정
# x와 y에 각각 어떤 데이터를 넣어서 그래프를 그릴건지 선택
x=d1['Category']
y=d1['Customer ID']

# 그래프 그리기 
# 보라색, * 으로 데이터포인트 표시, 투명도=50%, 라인 굵기 5
# marker는 그래프 위에 point로 표시되는 것으로, *, ^, . 등도 넣을 수 있다
plt.plot(x, y, color='purple', marker='o', alpha=0.5, linewidth=10)
plt.title("group by category - user cnt")
plt.xlabel("category")
plt.ylabel("usercnt")

# 카테고리, 성별 유저수 구하기 
# stack 은 pivot 테이블과 비슷하게, 데이터프레임을 핸들링하는 데 주로 사용됩니다. 
# 반대로 인덱스를 컬럼으로 풀어주는 unstack 이 있습니다. 
d2 = df2.groupby(['Category','Gender'])['Customer ID'].count().unstack(1)# 성별이 컬럼으로

unstack을 안 하면 아래와 같이 성별이 인덱스로 나오지만

unstack을 하면 컬럼으로 나온다.

막대 그래프 그리기

# python 내장함수 plot 사용하기
# 막대 그래프, 컬러는 hex code 를 사용하여 지정할 수 있습니다. 
# hex code 찾기: https://html-color-codes.info/
dplot8 = d2.plot(kind='bar',color=['#2F2FB1','#9b59b6'])
plt.title("bar plot1")
plt.xlabel("category")
plt.ylabel("usercnt")


누적 막대그래프 그리기

stacked=True를 추가하면 된다

# python 내장함수 plot 사용하기
# 카테고리, 성별 유저수 구하기 
# stacked=True 로 설정하면 누적그래프를 그릴 수 있습니다. 
dplot9 = d2.plot(kind='bar', stacked=True, color=['#F4D13B','#9b59b6'])
plt.title("bar plot2")
plt.xlabel("category")
plt.ylabel("usercnt")

파이 차트 그리기
piedf가 다음과 같을 때

옵션을 통해 파이 차트를 그릴 수 있다

#matplotlib 라이브러리를 통한 그래프 그리기
# 파이차트 그리기 
# labels 옵션을 통해 그룹값을 표현해줄 수 있습니다. 
dplot7= plt.figure(figsize=(7,3))
plt.pie(
    x=piedf['Customer ID'], 
    labels=piedf['Gender'],    # 파이 차트의 각 요소들이 어떤 건지 표시(네모 박스의 Female Male)
    # 소수점 첫째자리까지 표시
    # %1.20f이면 소수점 스무번째자리까지 표시
    autopct='%1.1f',
    colors=['red','#9b59b6'],
    startangle=90   # 파이 차트 안의 나뉘는 선의 각도를 조절
)
# 범례 표시하기 
plt.legend(piedf['Gender'])
# 타이틀명, 타이틀 위치 왼쪽, 타이틀 여백 50, 글자크기, 굵게 설정 
plt.title("pie plot", loc="center", pad=10, fontsize=10, fontweight="bold")
plt.show()

산점도 그리기

# matplotlib 라이브러리를 통한 그래프 그리기
# x축: 나이 / y축: 구매금액, 데이터 포인트 색상: purple 
plt.scatter(d3['Age'],d3['Purchase Amount (USD)'], c="purple")

이중축 그래프 그리기

# matplotlib 라이브러리와 내장함수를 통한 그래프 그리기
# 1. 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (4, 3)
plt.rcParams['font.size'] = 12

# 2. 데이터 준비
x = np.arange(2020, 2027)
y1 = np.array([1, 3, 7, 5, 9, 7, 14])
y2 = np.array([1, 3, 5, 7, 9, 11, 13])

# 3. 그래프 그리기- line 그래프 
# subplot 모듈을 사용하면 여러 개의 그래프를 동시에 시각화할 수 있습니다.
# 전체 도화지를 그려주고(figure) 위치에 각 그래프들을 배치한다고 이해해주세요.
fig, ax1 = plt.subplots()

# 라인 그래프
# 선 색상 초록, 굵기 5, 투명도 70%, 축 이름: Price
ax1.plot(x, y1, color='green', linewidth=5, alpha=0.7, label='Price')
# y 축 범뮈 설정
ax1.set_ylim(0, 30)
# y 축 이름 설정
ax1.set_ylabel('Price ($)')
# x 축 이름 설정
ax1.set_xlabel('Year')


# 3. 그래프 그리기- bar 그래프 
# x축 공유(즉, 이중축 사용 의미)
ax2 = ax1.twinx()
# 막대 보라색, 투명도 70%, 막대 넓이 0.7 
ax2.bar(x, y2, color='purple', label='Demand', alpha=0.7, width=0.7)
# y 축 범위 설정
ax2.set_ylim(0, 18)
# y 축 이름 설정
ax2.set_ylabel(r'Demand ($\times10^6$)')

# 레이블 위치 
# 뒤에 붙은 가중치가 클수록 가장 위쪽에 보여진다고 생각하면 됨. 
# 모든 그래프에 가중치를 다 줄 필요 없고, 가중치를 줘서 차이만 주면 됨
# ax2.set_zorder(ax1.get_zorder() + 10) #와 비교해보세요! 
ax1.set_zorder(ax2.get_zorder() + 20)
ax1.patch.set_visible(False)

# 범례 지정, 위치까지 함께 
ax1.legend(loc='upper left')
ax2.legend(loc='upper right')

plt.show()

피라미드 그래프 그리기

# matplotlib 라이브러리를 통한 그래프 그리기
# 나이대별 성별 유저수 구하기 
# 피라미드 차트 그리기 
# 나이 구간 설정
# 5살 단위로 나이 자르기
bins2 = [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]

# cut 활용 절대구간 나누기 
# bins 파라미터는 데이터를 나눌 구간의 경계를 정의 
# [0, 4, 8, 12, 24]는 0~4, 4~8, 8~12, 12~24의 네 구간으로 데이터를 나누겠다는 의미
# pd.cut() 안에 bins라는 파라미터가 있음
df2["bin"] = pd.cut(df2["Age"], bins = bins2)
# **bins라는 파라미터 안에 내가 만든 리스트 변수인 bins2를 대입한 것**
# 그러고 df2에 bin이라는 컬럼을 새로 만들어서 넣음

# apply 와 lambda 를 활용한 전체 컬럼에 대한 나이 구간 컬럼 추가하기 
#15는 15-20 으로 반환됨 
# 나이 구간이 15-20이면 15가 x.left 20이 x.right
df2["age"] = df2["bin"].apply(lambda x: str(x.left) + " - " + str(x.right))
# 나이 구간이 15,20으로 나뉘어 있으니까 더 보기 좋게 15-20으로 바꾸어 주고 age라는 컬럼으로 저장





위에 있는 코드에서 count()를 해서 저장해주었고 지금 코드는 피벗테이블로만 바꾸는 것이기 때문에 굳이 count를 안 써줘도 각 고객수가 value로 나오는 것

피라미드를 만들기 위해 대칭을 만들어준다


barh는 가로 그래프이다

여러 그래프를 그리는 방법

드디어 나왔다 seaborn~

# seaborn 라이브러리를 통한 그래프 그리기
p = ["#F4D13B","red"]
sns.set_palette(p)
plot1 = (sns.barplot(data=df33,x= "Gender",y= "Customer ID"))
# containers: 각 막대 / labels: 각 막대의 높이를 텍스트로 반환
# bar_label은 막대 위에 숫자를 써주는 것
# 각 막대(containers)위에 df33의 Customer ID컬럼에 들어 있는 값들을 써줘
# containers[0]만 되나봐 숫자 바꾸니까 막대 위에 숫자가 안 나옴
plot1.bar_label(plot1.containers[0], labels=df33['Customer ID'], fontsize=7, color='green')
plot1.set_title("User - bar chart")



df9이 다음과 같을 때

# seaborn 라이브러리를 통한 그래프 그리기
plt.figure(figsize=(15, 8))
dplot1 = sns.barplot(x="Date", y="user count", data=df9, palette='rainbow')
dplot1.set_xticklabels(dplot1.get_xticklabels(), rotation=270)   
#rotation은 x축 글씨의 각도를 말함
dplot1.set(title='Monthly Active User') # title barplot

# 바차트에 텍스트 추가하기
# 이런 방법도 있다...이건 복잡하니 위의 containers 쓰는 게 낫다~
# patches 는 각 막대를 의미 .
for p in dplot1.patches:
    # 각 바의 높이 구하기
    height = p.get_height()
    # X 축 시작점으로부터, 막대넓이의 중앙 지점에 텍스트 표시
    dplot1.text(x = p.get_x()+(p.get_width()/2),
    # 각 막대 높이에 10 을 더해준 위치에 텍스트 표시
    y = height-50,
    # 값을 정수로 포맷팅
    s = '{:.0f}'.format(height),
    # 중앙 정렬
    ha = 'center')


씨본은 groupby해서 count를 안 하고 count함수를 써서 바로 시각화 할 수 있다!!

# seaborn 라이브러리를 통한 그래프 그리기
# 시즌별 카테고리별 유저수(count 값과 동일) 구하기
plt.figure(figsize=(6, 5))
# hue 는 범례입니다.
dplot2 = sns.countplot(x='Category', hue='Gender', data=df2, palette='cubehelix')
dplot2.set(title='bar plot3')


히스토그램도 그릴 수 있고~

박스플롯도 그릴 수 있다~
x를 y로 바꾸면 그래프가 세로로 바뀐다

이것도 x랑 y 서로 바꾸면 가로로 바뀐다

상관관계 그래프 그리기

corr()함수를 쓰면 상관계수를 구할 수 있다.

# seaborn 라이브러리를 통한 그래프 그리기
# annot: 각 셀의 값(상관계수) 표기,camp 는 팔레트
dplot10 = sns.heatmap(df10.corr(), annot = True, cmap = 'PiYG') # camp =PiYG 도 넣어서 색상을 비교해보세요.
dplot10.set(title='corr plot')


조인트 그래프를 그릴 수도 있다~

Altair를 통해서 움직이는 그래프 그리기

# altair 라이브러리를 통한 그래프 그리기
# 월별 유저수 interactive 그래프 구현
source=df9
alt.Chart(source).mark_bar().encode(
    x='Date',
    y='user count'
).interactive() # 동적 구현(없애면 그래프 안 움직임)

# altair 라이브러리를 통한 그래프 그리기
source = df33
colors = ['#F4D13B','#9b59b6']
#innerRadius=50 >> 도넛 안 구멍의 크기 조절
dplot3 = (
alt.Chart(source).mark_arc(innerRadius=50).encode(
    theta="Customer ID",
    color="Gender",

).configure_range(category=alt.RangeScheme(colors))) # 컬러 반영하기
dplot3.title = "donut plot" # 타이틀 설정
dplot3
# altair 라이브러리를 통한 그래프 그리기
source = merge_df
colors = ['#F57AD5','#9b59b6']

# 선택(드래그) 영역 설정
brush = alt.selection_interval()
points = (alt.Chart(source).mark_point().encode(
    # Q: 양적 데이터 타입 / N: 범주형 데이터 타입
    x='Age:Q',
    y='Purchase Amount (USD):Q',
    # 선택되지 않은 부분은 회색으로 처리
    color=alt.condition(brush, 'Gender:N', alt.value('lightgray')),
).properties(  # 선택 가능영역 설정
    width=1000,
    height=300
)
.add_params(brush)) # 산점도에 드래그 영역 추가하는 코드

# 아래쪽 가로바차트
bars = alt.Chart(source).mark_bar().encode(
    y='Gender:N',
    color='Gender:N',
    x='sum(Customer ID):Q'
).properties(
    width=1000,
    height=100
).transform_filter(brush) # 산점도에서 선택된 데이터만 필터링해 막대 그래프에 반영

#산점도와 막대 그래프를 수직으로 결합
dplot4 = (points & bars)

**추가로!!!!!! 태블로 대신 표를 정리해서 페이지를 만들 수 있다

# 최초 1회만
# pip install datapane
# 공식홈페이지 참고
#https://docs.datapane.com/
# 라이브러리 import
import datapane as dp

##### 리포트 메인 시작 #####
#1개의 block 안에 2개의 page 가 있음
#첫번째 page에 하나의 block 이 있음
report = dp.Blocks(
    ## 1 페이지 시작
    dp.Page(
        ## 페이지 이름
        title="User",
        ## 최상단 블록 만들기 3개
        blocks=[
            # 첫번째 단락
            dp.Group(
                        dp.BigNumber(heading="Total Users", value="3,900 명"),
                        dp.BigNumber(heading="Avg Age", value="약 44세"),
                        dp.BigNumber(heading="Subscribe Users", value="1,053명"),
                        columns=3,
                    ),
            ## 두번째 단락
            dp.Group(
                        dp.BigNumber(heading="Total Amount", value="약 3.1 억원"),
                        dp.BigNumber(heading="ARPPU", value="81,000 원"),
                        columns=2,
                    ),
            # 세번째 단락
            dp.Select(dp.Group(dp.Group(dp.Plot(dplot1), columns=1),
                               dp.Group(dp.Plot(dplot8),dp.Plot(dplot9) ,dp.Plot(dplot7),dp.Plot(dplot6),dp.Plot(dplot2),dp.Plot(dplot5), columns=3),
                               dp.Group(dp.Plot(dplot3),dp.Plot(dplot10), columns=2)
                             ,label="USER!!!!!!!!!!!"),
                      dp.Group(dp.Plot(dplot4),columns=1,label="Revenue"))
                ],
            ),
    ### 2 페이지 시작
    dp.Page(title="Data", blocks=[dp.DataTable(source, label="Data")]),
)
dp.save_report(report, path='report.html')

채윤아 너가 필요하면 어떻게 잘 해봐,,,난 너를 믿어,,,화이팅!

0개의 댓글