12주차 · 데이터 시각화
12장. 데이터 시각화
Section titled “12장. 데이터 시각화”- “무엇을 x에 놓고, 무엇을 y에 놓는가”를 코드 전에 문장으로 먼저 정한다
- 제목 · 축 라벨 · 단위를 갖춘 그래프 설계안(spec)을 딕셔너리로 작성한다
- NumPy 배열로 데이터를 생성하고 처리한 뒤 시각화 파이프라인을 구성한다
- 데이터 질문에 맞는 그래프 종류(선/산점/막대)를 선택하는 기준을 설명한다
- 잘못된 축 범위·라벨 누락 등 오해 유발 요소를 식별하고 수정한다
- 결과를 관찰–원인–시사점 3문장으로 정리한다
시각화 quickstart: 코드 전에 이 4가지를 먼저 답하기
Section titled “시각화 quickstart: 코드 전에 이 4가지를 먼저 답하기”그래프를 그리기 전에 아래 4가지 질문에 답하세요.
- 무엇이 변하는가? → x축
- 무엇을 측정하는가? → y축
- 단위는 무엇인가? (s, V, dBm, Hz, Ω)
- 이 그래프의 핵심 메시지 한 줄은?
1) 그래프의 기초 구성 요소
Section titled “1) 그래프의 기초 구성 요소”| 요소 | 역할 | 빠진 경우 생기는 문제 |
|---|---|---|
| 제목 | ”이 그래프가 답하는 질문” | 독자가 목적을 모름 |
| x축 라벨 + 단위 | 입력 변수와 물리량 | 수치 의미 해석 불가 |
| y축 라벨 + 단위 | 출력 변수와 물리량 | 수치 의미 해석 불가 |
| 적절한 y축 범위 | 데이터 맥락 보존 | 변화가 과장되거나 묻힘 |
| 해석 문장 | 그래프 → 의사결정 | 숫자만 있고 결론 없음 |
2) matplotlib 기본 문법 (로컬 참고용)
Section titled “2) matplotlib 기본 문법 (로컬 참고용)”# 로컬 Python 전용 예시 (브라우저 PythonConsole에서는 실행되지 않습니다)import matplotlib.pyplot as pltimport numpy as np
t = np.linspace(0, 1, 100) # 시간축 (s)v = 3.3 * np.sin(2 * np.pi * 5 * t) # 5 Hz 정현파 (V)
plt.figure(figsize=(7, 4))plt.plot(t, v, linewidth=2, color='royalblue', label='V(t)')plt.title('5 Hz Sine Wave')plt.xlabel('Time (s)')plt.ylabel('Voltage (V)')plt.ylim(-4, 4)plt.grid(alpha=0.3)plt.legend()plt.show()처음 쓸 때 체크할 4가지
Section titled “처음 쓸 때 체크할 4가지”x와y길이가 같은지 먼저 확인한다 (len(x) == len(y))- 제목은 “무엇 vs 무엇” 또는 “현상 요약”으로 쓴다
- 축 라벨에는 단위를 반드시 포함한다
- 그래프 뒤에 반드시 해석 문장 1줄을 붙인다
3) 질문에 맞는 그래프 선택
Section titled “3) 질문에 맞는 그래프 선택”| 데이터 질문 | 권장 그래프 | 이유 |
|---|---|---|
| ”시간에 따라 값이 어떻게 변하나?” | 선 그래프(Line) | 추세와 기울기 확인 용이 |
| ”두 변수의 관계는?” | 산점도(Scatter) | 상관/분산 파악 용이 |
| ”범주별 크기 비교는?” | 막대 그래프(Bar) | 카테고리 비교 명확 |
| ”값 분포가 어떻게 생겼나?” | 히스토그램(Histogram) | 빈도 분포 확인 가능 |
4) Bad vs Good 그래프 예시
Section titled “4) Bad vs Good 그래프 예시”Bad 예시 — 오해 유발
Section titled “Bad 예시 — 오해 유발”# 로컬 Python 전용 예시import matplotlib.pyplot as plt
x = [1, 2, 3, 4]y = [51, 52, 53, 54]
plt.plot(x, y, color='red')plt.ylim(50.8, 54.2) # y축을 과도하게 잘라 변화가 과장됨plt.title('Result') # 제목이 모호함# 축 라벨·단위 없음plt.show()문제점: 축 라벨 없음 / 제목 모호 / y축 절단으로 작은 변화가 크게 보임
차트를 불러오는 중...
Good 예시 — 신뢰 가능
Section titled “Good 예시 — 신뢰 가능”# 로컬 Python 전용 예시import matplotlib.pyplot as plt
x = [1, 2, 3, 4]y = [51, 52, 53, 54]
plt.figure(figsize=(6, 4))plt.plot(x, y, marker='o', linewidth=2, color='royalblue', label='측정값')plt.title('출력 전압 vs 테스트 단계')plt.xlabel('테스트 단계 (-)')plt.ylabel('출력 전압 (V)')plt.ylim(0, 60) # 맥락을 보존하는 축 범위plt.grid(alpha=0.3)plt.legend()plt.show()개선점: 명확한 제목 / 단위 포함 축 라벨 / 데이터 맥락을 유지하는 y축 범위
차트를 불러오는 중...
5) 엔드-투-엔드 파이프라인: 데이터 생성 → 처리 → 설계안
Section titled “5) 엔드-투-엔드 파이프라인: 데이터 생성 → 처리 → 설계안”공학 시각화의 전형적인 흐름은 다음 3단계입니다.
- 데이터 생성: NumPy로 배열 생성 또는 측정값 로드
- 처리: 정규화, 통계, 필터링 등 원하는 계산 수행
- 설계안 작성:
plot_spec딕셔너리로 제목·축·데이터를 정리하고 self-check
# 로컬 Python 전용 — 전체 파이프라인 예시import numpy as npimport matplotlib.pyplot as plt
# 1) 데이터 생성 (NumPy)rng = np.random.default_rng(42)t = np.linspace(0, 1, 200) # 시간 (s)v = 5.0 * np.sin(2 * np.pi * 10 * t) # 10 Hz 신호 (V)v_noisy = v + 0.4 * rng.normal(size=t.size) # 잡음 추가
# 2) 처리 — 이동 평균 스무딩window = 10v_smooth = np.convolve(v_noisy, np.ones(window) / window, mode='same')
# 3) 시각화plt.figure(figsize=(8, 4))plt.plot(t, v_noisy, alpha=0.4, color='gray', label='Noisy')plt.plot(t, v_smooth, linewidth=2, color='royalblue', label='Smoothed')plt.title('10 Hz Sine Signal — Raw vs Smoothed')plt.xlabel('Time (s)')plt.ylabel('Voltage (V)')plt.legend()plt.grid(alpha=0.3)plt.show()6) 해석 문장 템플릿 (3문장)
Section titled “6) 해석 문장 템플릿 (3문장)”결과를 정리할 때 아래 3문장 구조를 사용하세요.
- 관찰: “A에서 B로 변할 때, C가 증가/감소했다.”
- 원인 가설: “이는 D 특성 때문으로 보인다.”
- 공학적 시사점: “따라서 E 조건에서 운용/설계를 권장한다.”
예시:
- 거리가 1m에서 6m로 증가할 때, RSSI가 -38 dBm에서 -60 dBm으로 감소했다.
- 이는 자유공간 경로손실이 거리의 로그에 비례해 증가하기 때문으로 보인다.
- 따라서 안정적인 수신을 위해 송수신 거리를 3m 이내로 유지하는 설계를 권장한다.
실제 차트 미리보기
Section titled “실제 차트 미리보기”위 설계안을 실제 그래프로 렌더링하면 이렇게 보입니다.
차트를 불러오는 중...
예제 1 줄별 해설
Section titled “예제 1 줄별 해설”- NumPy로 등간격 시간축과 정현파를 생성합니다. W11에서 배운
np.linspace와 vectorization을 그대로 활용합니다. plot_spec딕셔너리에 제목·축 라벨·데이터를 함께 묶어두면 실수를 줄일 수 있습니다.all([…])로 라벨이 모두 비어 있지 않은지 한 번에 검사합니다.- 플로팅 전에
min/max/mean으로 데이터 범위를 확인하면 축 범위 설정에 도움이 됩니다. assert로 x/y 길이가 같고 제목이 비어 있지 않음을 자동 확인합니다.
예제 2에서 새로 등장하는 개념
Section titled “예제 2에서 새로 등장하는 개념”| 개념 | 역할 | 예시 |
|---|---|---|
np.diff(v) / np.diff(t) | 구간 기울기(변화율) 계산 | RSSI 감소율 (dB/m) |
| f-string 출력 | 해석 문장을 코드로 자동 생성 | f"평균 기울기: {slope:.2f}" |
zip(a, b) | 두 배열을 인덱스별 쌍으로 순회 | for d, r in zip(distance_m, rssi_dbm): |
예제 2 줄별 해설
Section titled “예제 2 줄별 해설”- 측정 데이터를 NumPy 배열로 정의합니다.
dtype=float을 명시해 이후 나누기 연산이 정확하게 됩니다. np.diff로 인접 구간의 변화량을 구하고 거리 차이로 나눠 기울기(dB/m)를 얻습니다.plot_spec에 처리 결과와 원시 데이터를 함께 묶습니다.zip(distance_m, rssi_dbm)으로 인덱스 없이 두 배열을 동시에 순회합니다.- 3문장 해석 템플릿을 f-string으로 자동 완성합니다.
초보자 함정 표
Section titled “초보자 함정 표”| 실수 | 겉으로 보이는 문제 | 왜 위험한가 | 수정 방법 |
|---|---|---|---|
| 라벨·단위 누락 | x, y만 보임 | 물리적 의미 해석 불가 | Time (s), Voltage (V)처럼 명시 |
| y축 절단 미표기 | 작은 차이가 크게 보임 | 결론 왜곡 | 0 기준 또는 확대 표시 명시 |
| x/y 길이 불일치 | 런타임 오류 또는 이상한 그래프 | 데이터 오정렬 | assert len(x) == len(y) |
| 해석 문장 없음 | 그림만 있음 | 의사결정 근거 없음 | 관찰–원인–시사점 3문장 작성 |
| spec 라벨 빈 문자열 | "" 가 그대로 출력됨 | 독자에게 정보 없음 | all([title, x_label, y_label]) 점검 |
실습 문제 · 직접 코딩
Section titled “실습 문제 · 직접 코딩”[기초] 설계안 만들기: NumPy로 데이터를 생성하고 plot_spec 딕셔너리를 완성하세요.
[기초] 차트 타입 선택: 같은 데이터로 line_spec과 scatter_spec을 각각 만들고 차이를 출력하세요.
[응용] 기울기 계산: 전압-시간 데이터에서 구간 변화율을 계산하고 출력하세요.
[응용] 해석 문장 작성: 센서 데이터를 분석하고 관찰–원인–시사점 3문장을 f-string으로 출력하세요.
[도전] 다중 계열 설계안 + 해석: 두 안테나의 측정 데이터를 각각 설계안으로 만들고 NumPy로 통계를 비교한 뒤 해석 문장을 출력하세요.