스토리텔링 형식으로 업데이트되었습니다! 실무 사례와 함께 더 쉽게 이해할 수 있어요.
이미지 로딩 중...
AI Generated
2025. 11. 25. · 8 Views
범주형 변수 시각화 완벽 가이드 Bar Chart와 Count Plot
데이터 분석에서 가장 기본이 되는 범주형 변수 시각화 방법을 알아봅니다. Matplotlib의 Bar Chart부터 Seaborn의 Count Plot까지, 실무에서 바로 활용할 수 있는 시각화 기법을 배워봅니다.
목차
- Bar Chart 기초
- 가로 막대 그래프 barh
- Seaborn Count Plot
- 그룹별 비교 Grouped Bar Chart
- 정렬된 막대 그래프
- 스택형 막대 그래프
- 퍼센트 스택형 막대 그래프
- 막대에 값 표시하기
- 색상으로 강조하기
- 한글 폰트 설정
1. Bar Chart 기초
김개발 씨는 마케팅팀에서 받은 엑셀 데이터를 보고 있었습니다. "이번 분기 제품별 판매량을 시각화해서 보여주세요." 숫자만 나열된 표를 보여드리기보다 한눈에 비교할 수 있는 차트가 필요했습니다.
가장 먼저 떠오른 것이 바로 막대 그래프였습니다.
Bar Chart는 범주형 데이터의 값을 막대 길이로 표현하는 가장 기본적인 시각화 방법입니다. 마치 키 재기 줄에 서 있는 아이들처럼, 각 범주가 얼마나 큰 값을 가지는지 직관적으로 비교할 수 있습니다.
데이터 분석의 첫걸음이자 가장 많이 사용되는 차트입니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
# 제품별 판매량 데이터
products = ['노트북', '태블릿', '스마트폰', '이어폰']
sales = [150, 90, 200, 120]
# 기본 막대 그래프 생성
plt.figure(figsize=(8, 5))
plt.bar(products, sales, color='steelblue')
# 그래프 꾸미기
plt.title('제품별 판매량')
plt.xlabel('제품')
plt.ylabel('판매량 (대)')
plt.show()
김개발 씨는 입사 6개월 차 데이터 분석가입니다. 오늘 마케팅팀 이부장님께서 급하게 요청을 보내왔습니다.
"김개발 씨, 이번 분기 제품별 판매 현황을 내일 임원 회의에서 발표해야 하는데, 보기 좋게 정리해줄 수 있어요?" 엑셀 파일을 열어보니 노트북 150대, 태블릿 90대, 스마트폰 200대, 이어폰 120대라는 숫자가 적혀 있었습니다. 이 숫자들을 그대로 보여드리면 될까요?
아닙니다. 사람의 눈은 숫자보다 그림에 훨씬 민감하게 반응합니다.
그렇다면 Bar Chart란 정확히 무엇일까요? 쉽게 비유하자면, Bar Chart는 마치 수영장에서 레인별로 서 있는 선수들의 키를 비교하는 것과 같습니다.
각 레인에 한 명씩 서 있고, 누가 가장 키가 큰지 한눈에 알 수 있습니다. Bar Chart도 마찬가지로 각 범주를 나란히 세워두고 값의 크기를 막대 길이로 보여줍니다.
왜 Bar Chart가 필요할까요? 인간의 뇌는 숫자를 처리하는 것보다 시각적 패턴을 인식하는 데 훨씬 뛰어납니다.
"150, 90, 200, 120"이라는 숫자를 보면 잠시 생각해야 하지만, 막대 그래프를 보면 "스마트폰이 가장 많이 팔렸구나"라는 결론이 0.5초 만에 떠오릅니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 **plt.figure(figsize=(8, 5))**로 그래프의 크기를 설정합니다. 8은 가로 길이, 5는 세로 길이를 인치 단위로 나타냅니다.
다음으로 **plt.bar(products, sales)**가 핵심입니다. 첫 번째 인자로 x축에 표시할 범주들을, 두 번째 인자로 각 범주의 값을 전달합니다.
**color='steelblue'**는 막대의 색상을 지정합니다. 시각화에서 색상은 단순한 장식이 아닙니다.
적절한 색상은 데이터를 더 명확하게 전달하고, 보는 사람의 피로도를 줄여줍니다. 실제 현업에서는 어떻게 활용할까요?
전자상거래 회사에서는 월별 주문량을, 인사팀에서는 부서별 인원수를, 마케팅팀에서는 채널별 유입량을 Bar Chart로 시각화합니다. 가장 기본적이면서도 가장 강력한 도구입니다.
주의할 점도 있습니다. 범주가 너무 많으면 막대가 빽빽해져서 오히려 가독성이 떨어집니다.
일반적으로 10개 이내의 범주일 때 Bar Chart가 효과적입니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
완성된 Bar Chart를 본 이부장님은 만족스러운 표정을 지었습니다. "오, 스마트폰이 압도적이네.
한눈에 들어와서 좋아요!"
실전 팁
💡 - figsize를 적절히 조절하여 막대가 너무 뚱뚱하거나 가늘지 않게 설정하세요
- color 파라미터로 회사 브랜드 색상을 적용하면 프로페셔널해 보입니다
2. 가로 막대 그래프 barh
김개발 씨는 국가별 수출량 데이터를 시각화해달라는 요청을 받았습니다. 그런데 국가 이름이 길어서 세로 막대 그래프로 그리니 x축 라벨이 서로 겹쳐버렸습니다.
"이럴 땐 어떻게 해야 하지?" 선배 박시니어 씨가 힌트를 줬습니다. "막대를 눕혀봐."
**가로 막대 그래프(barh)**는 막대를 수평으로 배치하는 방식입니다. 범주 이름이 길거나 범주 개수가 많을 때 특히 유용합니다.
마치 책꽂이에 책을 눕혀 놓으면 책 제목이 잘 보이는 것처럼, 긴 라벨도 깔끔하게 표시할 수 있습니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
# 국가별 수출량 데이터
countries = ['대한민국', '미국', '중국', '독일', '일본']
exports = [180, 250, 320, 200, 170]
# 가로 막대 그래프 생성
plt.figure(figsize=(8, 5))
plt.barh(countries, exports, color='coral')
# 그래프 꾸미기
plt.title('국가별 수출량 비교')
plt.xlabel('수출량 (억 달러)')
plt.ylabel('국가')
plt.show()
김개발 씨가 국가별 수출량 데이터를 받았을 때의 일입니다. 처음에는 익숙한 세로 막대 그래프로 그렸습니다.
그런데 결과물을 보니 문제가 있었습니다. "대한민국", "미국", "중국" 같은 국가 이름이 x축에서 서로 겹쳐 보이는 것이었습니다.
라벨을 45도로 기울여볼까요? 그래도 어색합니다.
글자 크기를 줄여볼까요? 가독성이 떨어집니다.
이럴 때 해결책이 바로 가로 막대 그래프입니다. 가로 막대 그래프란 무엇일까요?
도서관 서가를 떠올려 보세요. 책을 세로로 꽂아두면 책등에 적힌 제목이 잘 보입니다.
하지만 제목이 아주 긴 책들은 눕혀서 쌓아두기도 합니다. 그러면 긴 제목도 한눈에 읽을 수 있습니다.
barh도 같은 원리입니다. **plt.bar()**가 세로 막대라면, **plt.barh()**는 가로 막대입니다.
h는 horizontal(수평)의 약자입니다. 사용법은 거의 동일합니다.
코드를 살펴보면, plt.bar()를 plt.barh()로 바꾸기만 하면 됩니다. 단, 축의 의미가 바뀝니다.
이제 y축에 범주가, x축에 값이 표시됩니다. 따라서 xlabel과 ylabel도 서로 바꿔줘야 합니다.
실무에서 가로 막대 그래프는 언제 쓸까요? 설문조사 결과를 발표할 때 많이 사용합니다.
"가장 선호하는 프로그래밍 언어는?"이라는 질문의 답변이 "JavaScript", "Python", "TypeScript" 같은 긴 이름이라면 가로 막대가 제격입니다. 또한 순위를 표현할 때도 좋습니다.
1등부터 10등까지 나열하면 위에서 아래로 자연스럽게 읽힙니다. 주의할 점이 있습니다.
시계열 데이터처럼 순서가 중요한 경우에는 가로 막대가 어색할 수 있습니다. 시간은 왼쪽에서 오른쪽으로 흐르는 것이 자연스럽기 때문입니다.
결국 세로냐 가로냐의 선택은 데이터의 특성과 라벨의 길이에 따라 결정됩니다. 김개발 씨는 국가 이름이 깔끔하게 표시된 가로 막대 그래프를 보며 뿌듯해했습니다.
실전 팁
💡 - 범주 이름이 길면 barh를, 짧으면 bar를 사용하세요
- 순위를 표현할 때는 가로 막대로 위에서 아래로 정렬하면 직관적입니다
3. Seaborn Count Plot
김개발 씨는 고객 데이터를 분석하던 중 한 가지 의문이 들었습니다. "각 연령대별로 고객이 몇 명이나 되지?" 데이터프레임에서 직접 value_counts()로 세어서 bar 차트를 그릴 수도 있지만, 뭔가 더 간단한 방법이 있을 것 같았습니다.
그때 Seaborn의 countplot을 발견했습니다.
Count Plot은 각 범주에 해당하는 데이터 개수를 자동으로 세어서 막대로 표현하는 차트입니다. Matplotlib의 bar는 값을 직접 전달해야 하지만, Seaborn의 countplot은 데이터프레임만 넘기면 알아서 빈도를 계산합니다.
마치 자동 계산기가 달린 저울 같습니다.
다음 코드를 살펴봅시다.
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
# 샘플 데이터 생성
data = pd.DataFrame({
'age_group': ['20대', '30대', '20대', '40대', '30대',
'20대', '30대', '40대', '20대', '30대']
})
# Count Plot 생성
plt.figure(figsize=(8, 5))
sns.countplot(data=data, x='age_group', palette='viridis')
plt.title('연령대별 고객 수')
plt.xlabel('연령대')
plt.ylabel('고객 수')
plt.show()
데이터 분석을 하다 보면 "이 범주에 데이터가 몇 개나 있지?"라는 질문을 자주 하게 됩니다. 김개발 씨도 고객 데이터를 받았을 때 가장 먼저 궁금했던 것이 연령대별 분포였습니다.
Matplotlib의 bar 차트로 이 작업을 하려면 어떻게 해야 할까요? 먼저 value_counts()로 각 범주의 개수를 세고, 그 결과를 bar()에 전달해야 합니다.
코드가 두세 줄 더 필요합니다. 데이터가 복잡해질수록 이런 전처리 과정이 번거로워집니다.
바로 이런 불편함을 해결하기 위해 Seaborn이 등장했습니다. Seaborn은 Matplotlib 위에 구축된 고수준 시각화 라이브러리입니다.
마치 자동 변속기가 달린 자동차처럼, 복잡한 조작 없이도 원하는 결과를 얻을 수 있습니다. 그중에서도 countplot은 빈도 계산을 자동화한 함수입니다.
코드를 보면, **sns.countplot(data=data, x='age_group')**이 핵심입니다. data에 데이터프레임을, x에 범주형 컬럼명을 전달하면 끝입니다.
Seaborn이 알아서 각 범주의 개수를 세고 막대를 그립니다. **palette='viridis'**는 색상 팔레트를 지정합니다.
Seaborn은 다양한 팔레트를 제공하는데, viridis는 색맹인 분들도 구분할 수 있도록 설계된 팔레트입니다. 실무에서 발표 자료를 만들 때 이런 배려가 중요합니다.
그렇다면 언제 bar를 쓰고 언제 countplot을 쓸까요? 이미 집계된 데이터가 있다면 bar를 씁니다.
예를 들어 "노트북 150대, 태블릿 90대"처럼 값이 정해져 있으면 bar가 적합합니다. 반면 원본 데이터에서 빈도를 세야 한다면 countplot이 편리합니다.
김개발 씨는 countplot으로 연령대별 분포를 그려보니 30대 고객이 가장 많다는 것을 한눈에 알 수 있었습니다. "역시 도구를 제대로 알면 일이 훨씬 쉬워지는구나."
실전 팁
💡 - 원본 데이터의 빈도를 시각화할 때는 countplot이 편리합니다
- palette 옵션으로 시각적으로 구분되는 색상을 적용하세요
4. 그룹별 비교 Grouped Bar Chart
이번에는 더 복잡한 요청이 들어왔습니다. "제품별 판매량을 분기별로 비교해서 보여줘." 단순히 제품별 합계만 보여주는 것이 아니라, 1분기와 2분기를 나란히 비교해야 합니다.
김개발 씨는 고민에 빠졌습니다. 막대를 어떻게 배치해야 할까요?
Grouped Bar Chart는 두 개 이상의 범주를 함께 비교하는 차트입니다. 하나의 주 범주 안에서 보조 범주별로 막대를 나란히 배치합니다.
마치 반별로 남학생과 여학생 키를 나란히 비교하는 것처럼, 다차원 비교가 가능해집니다.
다음 코드를 살펴봅시다.
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
# 분기별 제품 판매 데이터
data = pd.DataFrame({
'product': ['노트북', '태블릿', '스마트폰'] * 2,
'quarter': ['1분기']*3 + ['2분기']*3,
'sales': [150, 90, 200, 180, 100, 220]
})
# Grouped Bar Chart 생성
plt.figure(figsize=(10, 6))
sns.barplot(data=data, x='product', y='sales', hue='quarter')
plt.title('분기별 제품 판매량 비교')
plt.xlabel('제품')
plt.ylabel('판매량')
plt.legend(title='분기')
plt.show()
데이터 분석에서 한 가지 기준으로만 비교하는 경우는 드뭅니다. 대부분 "A 기준으로 나눈 다음, 다시 B 기준으로 비교해줘"라는 요청을 받습니다.
제품별로 나누고 분기별로 비교하거나, 지역별로 나누고 성별로 비교하는 식입니다. 이럴 때 사용하는 것이 Grouped Bar Chart입니다.
쉽게 비유하자면, 초등학교 운동회에서 반별 달리기 기록을 비교한다고 생각해보세요. 1반 남학생과 여학생, 2반 남학생과 여학생의 기록을 한눈에 비교하려면 어떻게 할까요?
각 반 아래에 남녀 막대를 나란히 세우면 됩니다. 이것이 Grouped Bar Chart의 원리입니다.
Seaborn의 barplot에서 핵심은 hue 파라미터입니다. x에는 주 범주(제품)를, y에는 값(판매량)을, hue에는 보조 범주(분기)를 지정합니다.
hue를 지정하면 Seaborn이 자동으로 막대를 나란히 배치하고 색상으로 구분합니다. 범례도 자동으로 생성됩니다.
코드에서 **plt.legend(title='분기')**는 범례에 제목을 붙이는 부분입니다. 범례가 무엇을 의미하는지 명확히 해주면 차트를 처음 보는 사람도 쉽게 이해할 수 있습니다.
실무에서 Grouped Bar Chart는 정말 자주 사용됩니다. A/B 테스트 결과를 발표할 때 "A그룹과 B그룹의 전환율을 페이지별로 비교"하거나, 매출 보고서에서 "올해와 작년의 월별 매출 비교"를 보여줄 때 이 차트가 제격입니다.
주의할 점이 있습니다. 보조 범주가 너무 많으면 막대가 너무 가늘어져서 가독성이 떨어집니다.
보조 범주는 2~4개 정도가 적당합니다. 김개발 씨의 분기별 비교 차트를 본 마케팅팀은 만족스러워했습니다.
"오, 스마트폰이 1분기보다 2분기에 더 많이 팔렸네. 이 추세라면 3분기도 기대되겠어!"
실전 팁
💡 - hue 파라미터로 두 번째 범주를 지정하면 그룹별 비교가 가능합니다
- 보조 범주는 2~4개 이내로 유지하는 것이 가독성에 좋습니다
5. 정렬된 막대 그래프
김개발 씨가 만든 차트를 본 박시니어 씨가 한마디 했습니다. "데이터가 정렬되어 있지 않으면 비교하기 어려워.
가장 큰 값이 뭔지 한눈에 들어와야 해." 그 말을 듣고 보니, 막대들이 제멋대로 배치되어 있어서 어떤 항목이 가장 큰지 찾는 데 시간이 걸렸습니다.
정렬된 막대 그래프는 데이터를 크기순으로 배열하여 비교를 쉽게 만듭니다. 가장 큰 값이 맨 위나 맨 앞에 오도록 정렬하면, 보는 사람이 핵심 정보를 즉시 파악할 수 있습니다.
마치 성적순으로 줄을 세우면 1등이 바로 보이는 것처럼요.
다음 코드를 살펴봅시다.
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
# 브랜드별 매출 데이터
data = pd.DataFrame({
'brand': ['삼성', 'LG', '애플', '샤오미', '화웨이'],
'revenue': [320, 180, 450, 150, 200]
})
# 매출 기준 내림차순 정렬
data_sorted = data.sort_values('revenue', ascending=False)
# 정렬된 막대 그래프
plt.figure(figsize=(10, 6))
sns.barplot(data=data_sorted, x='brand', y='revenue',
order=data_sorted['brand'], palette='Blues_d')
plt.title('브랜드별 매출 순위')
plt.xlabel('브랜드')
plt.ylabel('매출 (억 원)')
plt.show()
시각화의 목적은 데이터에서 인사이트를 빠르게 추출하는 것입니다. 정렬되지 않은 막대 그래프는 이 목적을 방해합니다.
눈이 이리저리 돌아다니면서 "어디가 제일 크지?" 하고 찾아야 하기 때문입니다. 인간의 눈은 패턴을 좋아합니다.
계단처럼 점점 작아지는 막대를 보면 뇌가 편안함을 느낍니다. 반면 들쭉날쭉한 막대를 보면 혼란스러워합니다.
정렬은 단순한 미적 선택이 아니라 정보 전달 효율성의 문제입니다. 코드를 살펴보면, 먼저 **sort_values('revenue', ascending=False)**로 데이터프레임을 정렬합니다.
ascending=False는 내림차순, 즉 큰 값부터 작은 값 순으로 정렬하라는 의미입니다. 여기서 중요한 것이 order 파라미터입니다.
Seaborn의 barplot은 기본적으로 데이터가 나타나는 순서대로 막대를 배치합니다. 하지만 order에 원하는 순서를 명시적으로 전달하면 그 순서를 따릅니다.
정렬된 데이터프레임의 brand 컬럼을 order로 전달하면 정렬 순서가 유지됩니다. **palette='Blues_d'**는 파란색 계열의 그라데이션 팔레트입니다.
이렇게 하면 가장 큰 값이 진한 파란색, 작은 값이 연한 파란색으로 표시되어 시각적 강조 효과를 얻을 수 있습니다. 실무에서 정렬은 선택이 아닌 필수입니다.
매출 순위, 판매량 순위, 선호도 순위 등 순위를 보여주는 차트라면 반드시 정렬해야 합니다. 정렬되지 않은 순위 차트는 의미가 없습니다.
다만 시계열 데이터는 예외입니다. 월별 매출처럼 시간 순서가 중요한 데이터는 1월, 2월, 3월 순으로 배치해야 합니다.
값의 크기로 정렬하면 시간의 흐름을 읽을 수 없게 됩니다. 김개발 씨는 정렬된 차트를 보며 깨달았습니다.
"애플이 1등이고, 삼성이 2등이구나. 한눈에 들어와!"
실전 팁
💡 - 순위나 비교가 목적이라면 반드시 정렬하세요
- 시계열 데이터는 시간 순서대로, 범주 데이터는 값 크기로 정렬하세요
6. 스택형 막대 그래프
이번에는 전체 대비 부분의 비율을 보여달라는 요청이 왔습니다. "각 지역의 총 매출도 중요하지만, 그 안에서 제품별 비중이 어떤지도 알고 싶어요." 단순히 그룹별로 나란히 세우는 것으로는 부족했습니다.
막대 하나에 여러 정보를 담아야 했습니다.
**스택형 막대 그래프(Stacked Bar Chart)**는 하나의 막대 안에 여러 범주를 쌓아 올리는 방식입니다. 전체 합계와 함께 각 부분의 기여도를 동시에 보여줄 수 있습니다.
마치 샌드위치의 층층이 쌓인 재료처럼, 각 부분이 전체에서 얼마를 차지하는지 한눈에 파악됩니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
import numpy as np
# 지역별 제품 매출 데이터
regions = ['서울', '부산', '대구', '인천']
laptop = [80, 50, 30, 40]
tablet = [40, 30, 20, 25]
phone = [60, 45, 35, 30]
# 스택형 막대 그래프
x = np.arange(len(regions))
width = 0.6
plt.figure(figsize=(10, 6))
plt.bar(x, laptop, width, label='노트북', color='#3498db')
plt.bar(x, tablet, width, bottom=laptop, label='태블릿', color='#2ecc71')
plt.bar(x, phone, width, bottom=np.array(laptop)+np.array(tablet),
label='스마트폰', color='#e74c3c')
plt.xticks(x, regions)
plt.title('지역별 제품 매출 구성')
plt.xlabel('지역')
plt.ylabel('매출 (억 원)')
plt.legend()
plt.show()
데이터 시각화에서 "전체"와 "부분"을 동시에 보여줘야 할 때가 있습니다. 단순히 항목별로 나열하면 전체 합계가 안 보이고, 합계만 보여주면 구성 비율이 안 보입니다.
이 딜레마를 해결하는 것이 스택형 막대 그래프입니다. 아파트를 생각해보세요.
건물 전체 높이를 보면 몇 층인지 알 수 있고, 각 층을 보면 그 층이 전체에서 얼마를 차지하는지 알 수 있습니다. 스택형 막대 그래프도 마찬가지입니다.
막대 전체 높이는 총합을, 각 색상 영역은 개별 항목의 기여도를 나타냅니다. 코드에서 핵심은 bottom 파라미터입니다.
첫 번째 plt.bar()는 바닥(0)부터 노트북 매출만큼 막대를 그립니다. 두 번째 plt.bar()는 bottom=laptop으로 노트북 막대 위에서 시작하여 태블릿 매출만큼 더 쌓습니다.
세 번째는 노트북+태블릿 위에 스마트폰을 쌓습니다. **np.array()**로 리스트를 배열로 변환하는 이유는 리스트끼리는 덧셈이 안 되기 때문입니다.
NumPy 배열은 요소별 덧셈을 지원합니다. Seaborn에서도 스택형 차트를 그릴 수 있을까요?
아쉽게도 Seaborn에는 스택형 막대 그래프를 직접 그리는 함수가 없습니다. Matplotlib으로 직접 그리거나 Pandas의 plot 메서드를 활용해야 합니다.
스택형 차트의 단점도 알아야 합니다. 가장 아래 항목(노트북)과 가장 위 항목(스마트폰)은 비교하기 쉽지만, 가운데 항목(태블릿)은 시작점이 제각각이라 비교가 어렵습니다.
따라서 가장 중요한 항목을 맨 아래에 배치하는 것이 좋습니다. 김개발 씨는 스택형 차트를 완성하고 나서야 깨달았습니다.
"서울이 총 매출은 가장 높지만, 노트북 비중이 특히 크구나!"
실전 팁
💡 - 가장 중요한 범주를 막대의 가장 아래에 배치하세요
- 범주가 3개를 초과하면 가독성이 떨어지므로 주의하세요
7. 퍼센트 스택형 막대 그래프
스택형 차트를 보던 기획팀에서 추가 요청이 왔습니다. "각 지역의 총 매출 금액보다는 제품별 비율이 더 궁금해요.
서울에서 노트북 비중이 40%인지 50%인지 정확히 알고 싶어요." 절대값이 아닌 상대값, 즉 비율을 보여줘야 하는 상황이었습니다.
퍼센트 스택형 막대 그래프는 모든 막대의 높이를 100%로 통일하고 각 범주의 비율을 보여줍니다. 전체 크기가 다른 항목들 사이에서 구성 비율만을 비교할 때 유용합니다.
마치 파이 차트를 막대 형태로 펼쳐놓은 것과 같습니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
import numpy as np
# 지역별 제품 매출 데이터
regions = ['서울', '부산', '대구', '인천']
laptop = np.array([80, 50, 30, 40])
tablet = np.array([40, 30, 20, 25])
phone = np.array([60, 45, 35, 30])
# 퍼센트 계산
totals = laptop + tablet + phone
laptop_pct = laptop / totals * 100
tablet_pct = tablet / totals * 100
phone_pct = phone / totals * 100
# 퍼센트 스택형 막대 그래프
x = np.arange(len(regions))
width = 0.6
plt.figure(figsize=(10, 6))
plt.bar(x, laptop_pct, width, label='노트북')
plt.bar(x, tablet_pct, width, bottom=laptop_pct, label='태블릿')
plt.bar(x, phone_pct, width, bottom=laptop_pct+tablet_pct, label='스마트폰')
plt.xticks(x, regions)
plt.title('지역별 제품 매출 비율')
plt.ylabel('비율 (%)')
plt.ylim(0, 100)
plt.legend()
plt.show()
앞서 본 일반 스택형 차트는 절대값을 보여줍니다. 서울의 막대가 가장 높다면 서울의 총 매출이 가장 크다는 의미입니다.
하지만 때로는 절대값보다 상대값이 더 중요할 때가 있습니다. 예를 들어, 서울과 대구의 총 매출은 다르지만 제품 구성 비율은 비슷할 수 있습니다.
또는 총 매출은 비슷한데 구성 비율이 완전히 다를 수도 있습니다. 이런 인사이트를 얻으려면 퍼센트 스택형 차트가 필요합니다.
만드는 방법은 간단합니다. 먼저 각 지역의 총합을 계산합니다.
그다음 각 항목을 총합으로 나누고 100을 곱해 퍼센트로 변환합니다. 이렇게 하면 모든 막대의 높이가 100%로 통일됩니다.
코드에서 totals = laptop + tablet + phone이 각 지역의 총합을 계산하는 부분입니다. NumPy 배열은 같은 위치의 요소끼리 더해주므로, 서울 총합, 부산 총합, 대구 총합, 인천 총합이 한 번에 계산됩니다.
**plt.ylim(0, 100)**으로 y축 범위를 0~100으로 고정하면 모든 막대가 같은 높이로 보입니다. 이렇게 하면 비율 비교에만 집중할 수 있습니다.
퍼센트 스택형 차트는 언제 쓸까요? 시장 점유율 비교, 예산 배분 비교, 인구 구성비 비교 등 "전체 대비 비율"이 핵심인 분석에 적합합니다.
반면 절대적인 크기도 중요하다면 일반 스택형 차트를 쓰는 것이 맞습니다. 김개발 씨의 차트를 본 기획팀은 만족했습니다.
"오, 대구는 스마트폰 비중이 다른 지역보다 높네요. 대구 지역 스마트폰 마케팅을 강화해볼까요?"
실전 팁
💡 - 절대값보다 비율이 중요할 때 퍼센트 스택형을 사용하세요
- plt.ylim(0, 100)으로 y축을 고정하면 더 명확해집니다
8. 막대에 값 표시하기
프레젠테이션 리허설에서 김개발 씨는 피드백을 받았습니다. "차트는 좋은데, 정확한 숫자를 알고 싶을 때가 있어요.
막대 위에 값을 표시해줄 수 있나요?" 시각적 비교도 중요하지만, 정확한 수치 정보도 필요한 상황이었습니다.
막대에 값 표시하기는 각 막대의 위나 안에 정확한 수치를 텍스트로 추가하는 기법입니다. 시각적 비교와 정확한 수치 정보를 동시에 제공할 수 있습니다.
특히 발표 자료나 보고서에서 "정확히 얼마인가요?"라는 질문에 미리 답할 수 있습니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
products = ['노트북', '태블릿', '스마트폰', '이어폰']
sales = [150, 90, 200, 120]
plt.figure(figsize=(8, 5))
bars = plt.bar(products, sales, color='steelblue')
# 막대 위에 값 표시
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height,
f'{int(height)}',
ha='center', va='bottom', fontsize=11)
plt.title('제품별 판매량')
plt.xlabel('제품')
plt.ylabel('판매량 (대)')
plt.show()
막대 그래프의 장점은 시각적으로 빠르게 비교할 수 있다는 것입니다. 하지만 "스마트폰 판매량이 정확히 몇 대야?"라는 질문에는 답하기 어렵습니다.
눈대중으로 "200쯤?"이라고 추측할 수는 있지만 정확하지 않습니다. 이 문제를 해결하는 것이 데이터 라벨입니다.
코드를 보면, **plt.bar()**의 반환값을 bars 변수에 저장합니다. 이 반환값은 막대 객체들의 컬렉션입니다.
각 막대 객체는 위치, 크기, 높이 등의 정보를 가지고 있습니다. for bar in bars: 반복문으로 각 막대를 순회합니다.
**bar.get_height()**로 막대의 높이(값)를 가져오고, **bar.get_x() + bar.get_width()/2.**로 막대의 중앙 x좌표를 계산합니다. **plt.text()**는 텍스트를 그래프에 추가하는 함수입니다.
첫 번째 인자는 x좌표, 두 번째 인자는 y좌표, 세 번째 인자는 표시할 텍스트입니다. **ha='center'**는 텍스트를 가로로 중앙 정렬, **va='bottom'**은 텍스트의 아래쪽을 기준점으로 삼는다는 의미입니다.
Matplotlib 3.4 버전부터는 더 간단한 방법도 있습니다. **plt.bar_label(bars)**를 사용하면 반복문 없이 한 줄로 라벨을 추가할 수 있습니다.
하지만 세밀한 조정이 필요한 경우에는 위의 방법이 더 유연합니다. 값 표시 위치는 데이터에 따라 달라져야 합니다.
막대가 짧으면 막대 위에 표시하고, 막대가 길면 막대 안쪽 상단에 표시하는 것이 자연스럽습니다. 김개발 씨의 발표는 완벽했습니다.
청중이 "스마트폰 판매량이 얼마죠?"라고 질문하기도 전에 200이라는 숫자가 막대 위에 선명하게 보였습니다.
실전 팁
💡 - Matplotlib 3.4 이상이라면 plt.bar_label()을 사용하면 간편합니다
- 값이 소수점인 경우 포맷 문자열로 자릿수를 조절하세요
9. 색상으로 강조하기
발표 자료를 검토하던 팀장님이 말했습니다. "전체적으로 잘 만들었는데, 핵심 메시지가 뭔지 한눈에 안 들어와.
우리가 강조하고 싶은 건 스마트폰 판매량이 가장 높다는 거잖아. 그게 확 눈에 띄어야 해."
색상 강조는 특정 막대만 다른 색으로 표시하여 시각적 주목도를 높이는 기법입니다. 모든 막대가 같은 색이면 어디를 봐야 할지 모릅니다.
핵심 데이터에 강조색을 적용하면 메시지 전달력이 크게 향상됩니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
products = ['노트북', '태블릿', '스마트폰', '이어폰']
sales = [150, 90, 200, 120]
# 최대값에만 강조색 적용
colors = ['lightgray' if s != max(sales) else '#e74c3c' for s in sales]
plt.figure(figsize=(8, 5))
bars = plt.bar(products, sales, color=colors)
# 최대값 막대 위에 값 표시
for bar, sale in zip(bars, sales):
if sale == max(sales):
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height,
f'{int(height)} (최고!)', ha='center', va='bottom',
fontsize=12, fontweight='bold', color='#e74c3c')
plt.title('제품별 판매량')
plt.xlabel('제품')
plt.ylabel('판매량 (대)')
plt.show()
시각화의 목적은 단순히 데이터를 보여주는 것이 아닙니다. 스토리를 전달하는 것입니다.
모든 데이터가 똑같이 중요한 것처럼 보이면 청중은 어디에 집중해야 할지 모릅니다. 신문 기사를 생각해보세요.
헤드라인은 굵은 글씨로, 본문은 일반 글씨로 표시됩니다. 독자는 헤드라인만 보고도 기사의 핵심을 파악합니다.
시각화도 마찬가지입니다. 코드의 핵심은 조건부 색상 리스트입니다.
**[... for s in sales]**는 리스트 컴프리헨션이라는 파이썬 문법입니다.
판매량이 최대값이 아니면 'lightgray', 최대값이면 '#e74c3c'(빨간색)를 할당합니다. 이렇게 생성된 colors 리스트를 plt.bar()의 color 파라미터에 전달합니다.
강조하는 기준은 다양할 수 있습니다. 최대값, 최소값, 목표 달성 여부, 전년 대비 성장률 등 메시지에 따라 강조 기준이 달라집니다.
예를 들어 "목표를 달성한 제품"을 강조하고 싶다면 목표값과 비교하는 조건을 사용하면 됩니다. 색상 선택도 중요합니다.
강조색은 일반색과 확실히 구분되어야 합니다. 빨간색, 주황색 같은 따뜻한 색이 강조에 효과적입니다.
반면 파란색, 회색 같은 차가운 색은 배경으로 적합합니다. 주의할 점이 있습니다.
강조하는 막대가 너무 많으면 강조의 의미가 사라집니다. 전체 막대의 20~30% 이하만 강조하는 것이 효과적입니다.
팀장님은 수정된 차트를 보고 만족스럽게 고개를 끄덕였습니다. "이제야 스마트폰이 확 눈에 들어오네.
좋아!"
실전 팁
💡 - 전달하고자 하는 핵심 메시지에 맞춰 강조 기준을 정하세요
- 강조색은 전체의 20~30% 이하로 제한해야 효과적입니다
10. 한글 폰트 설정
김개발 씨가 만든 멋진 차트를 저장하고 열어보니 충격적인 일이 벌어졌습니다. 제목과 축 라벨이 모두 네모 박스로 표시되어 있었습니다.
"아니, 분명히 한글로 잘 보였는데!" 이것이 바로 악명 높은 한글 폰트 깨짐 문제입니다.
한글 폰트 설정은 Matplotlib에서 한국어를 올바르게 표시하기 위한 필수 설정입니다. 기본 폰트는 한글을 지원하지 않아 사각형으로 표시됩니다.
한글 폰트를 명시적으로 지정하면 이 문제를 해결할 수 있습니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
import platform
# 운영체제별 한글 폰트 설정
if platform.system() == 'Windows':
font_name = font_manager.FontProperties(fname='c:/Windows/Fonts/malgun.ttf').get_name()
rc('font', family=font_name)
elif platform.system() == 'Darwin': # macOS
rc('font', family='AppleGothic')
else: # Linux
rc('font', family='NanumGothic')
# 마이너스 기호 깨짐 방지
plt.rcParams['axes.unicode_minus'] = False
# 이제 한글이 정상적으로 표시됩니다
plt.figure(figsize=(8, 5))
plt.bar(['노트북', '태블릿'], [150, 90])
plt.title('제품별 판매량')
plt.show()
한글 깨짐 문제는 파이썬 데이터 시각화를 처음 시작하는 분들이 가장 많이 겪는 문제 중 하나입니다. 분명히 화면에서는 잘 보이는데 저장하거나 공유하면 깨지는 경우도 있습니다.
왜 이런 문제가 발생할까요? Matplotlib은 미국에서 만들어진 라이브러리입니다.
기본 폰트인 DejaVu Sans는 영어, 숫자, 일부 유럽 언어만 지원합니다. 한글, 중국어, 일본어 같은 동아시아 언어는 포함되어 있지 않습니다.
따라서 한글을 표시하려고 하면 "이 글자를 어떻게 그려야 할지 모르겠어요"라며 사각형을 표시합니다. 해결책은 한글을 지원하는 폰트를 명시적으로 지정하는 것입니다.
코드에서 **platform.system()**은 현재 운영체제를 확인합니다. Windows라면 '맑은 고딕', macOS라면 'Apple Gothic', Linux라면 'NanumGothic'을 사용합니다.
각 운영체제에서 기본 제공하는 한글 폰트입니다. **rc('font', family=font_name)**은 Matplotlib의 기본 폰트를 변경합니다.
이 설정은 이후 생성되는 모든 그래프에 적용됩니다. 한 가지 더 주의할 점이 있습니다.
plt.rcParams['axes.unicode_minus'] = False 설정이 없으면 음수 기호(-)가 깨집니다. 한글 폰트로 바꾸면 마이너스 기호를 유니코드 문자로 인식하는데, 일부 폰트에서 이를 제대로 지원하지 않기 때문입니다.
이 설정 코드는 보통 노트북 맨 위에 한 번만 실행하면 됩니다. 매번 그래프를 그릴 때마다 설정할 필요는 없습니다.
김개발 씨는 폰트 설정 코드를 추가한 후 다시 차트를 저장해보았습니다. "제품별 판매량"이라는 제목이 선명하게 표시되었습니다.
"휴, 이제야 제대로 보이네!"
실전 팁
💡 - 코드 상단에 폰트 설정을 추가하고 재사용하세요
- Google Colab에서는 !apt-get install fonts-nanum으로 나눔폰트를 설치해야 합니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
이변량 분석 완벽 가이드: 변수 간 관계 탐색
두 변수 사이의 관계를 분석하는 이변량 분석의 핵심 개념과 기법을 배웁니다. 상관관계, 산점도, 교차분석 등 데이터 분석의 필수 도구들을 실습과 함께 익혀봅시다.
단변량 분석 분포 시각화 완벽 가이드
데이터 분석의 첫걸음인 단변량 분석과 분포 시각화를 배웁니다. 히스토그램, 박스플롯, 밀도 그래프 등 다양한 시각화 방법을 초보자도 쉽게 이해할 수 있도록 설명합니다.
데이터 타입 변환 및 정규화 완벽 가이드
데이터 분석과 머신러닝에서 가장 기초가 되는 데이터 타입 변환과 정규화 기법을 배워봅니다. 실무에서 자주 마주치는 데이터 전처리 문제를 Python으로 쉽게 해결하는 방법을 알려드립니다.
이상치 탐지 및 처리 완벽 가이드
데이터 속에 숨어있는 이상한 값들을 찾아내고 처리하는 방법을 배워봅니다. 실무에서 자주 마주치는 이상치 문제를 Python으로 해결하는 다양한 기법을 소개합니다.
결측치 처리 전략 완벽 가이드
데이터 분석에서 가장 먼저 만나는 문제, 결측치! 삭제부터 고급 대체 기법까지, 실무에서 바로 쓸 수 있는 결측치 처리 전략을 초급자도 이해하기 쉽게 알려드립니다. 데이터의 품질을 높이고 정확한 분석 결과를 얻어보세요.