Figure와 Table 제작
먼저 읽을 장 23.6 결과 분석과 주장의 범위
논문을 펼친 독자가 가장 먼저 보는 것은 그림이다. 초록 다음으로 그림과 캡션을 훑고, 거기서 핵심 결과를 이해하면 본문을 읽는다. 그래서 그림은 장식이 아니라 주장의 근거를 가장 빠르게 전달하는 수단이다. 같은 데이터로도 축 범위, 오차 막대의 종류, 색 하나에 따라 그림은 정확한 결론을 전하기도 하고 없는 효과를 만들어 내기도 한다.
이 장은 메시지가 분명하고 정직한 그림과 표를 만드는 원칙, 그리고 그 그림을 결과 파일에서 언제든 다시 만들 수 있는 파이프라인을 다룬다. 23.6장의 주장–근거 표(논문을 쓰는 중이면 23.8장의 주장 목록)에서 각 주장에 대응하는 그림이 이 장의 대상이다. 오차 막대에 쓰는 통계량(표준편차·표준오차·신뢰구간)은 12.5장에서 다뤘다.
학습 목표
- 메시지가 분명한 figure를 만든다
- 재현 가능한 그림 생성 파이프라인을 갖춘다
figure의 역할
한 그림, 한 메시지. 그림 하나는 문장 하나를 증명한다. "B는 상온과 고온에서 A보다 오차가 작고, 저온에서는 크다"처럼 그림이 말할 문장을 먼저 쓰고, 그 문장에 필요한 것만 그린다. 그 문장을 쓸 수 없다면 그림이 무엇을 보여 주려는지 저자도 모르는 것이다. Rougier 외(2014)의 "그림을 더 좋게 만드는 열 가지 규칙"도 청중을 알고 메시지를 정하는 것에서 시작한다.
그림의 종류.
- 개념도(schematic): 방법의 구조, 데이터의 흐름, 실험 장치. 논문의 첫 그림인 경우가 많고, 독자가 방법을 한눈에 이해하게 한다. 수치를 담지 않으므로 정확성보다 단순함이 중요하다.
- 결과 그림: 주장의 근거가 되는 측정값. 비교 대상, 변동성, 조건이 모두 보여야 한다.
- 진단 그림: 학습 곡선, 잔차, 오차 분포. 대개 부록에 두지만, 주장의 전제(학습이 수렴했다, 잔차에 구조가 없다)를 보이는 데 쓴다.
메시지에 맞는 형태. 무엇을 비교하는지가 그림의 형태를 정한다.
| 메시지 | 형태 |
|---|---|
| 두 방법의 차이 | 짝지은 점(같은 seed끼리 선으로 연결), 차이와 구간을 직접 그린 점 그림 |
| 양의 추세 | 선 그래프. 가로축은 연속 변수 |
| 여러 자릿수에 걸친 값 | 로그 축 |
| 분포의 모양 | 히스토그램, 상자 그림, 개별 점 |
| 2차원 장(field) | 지각적으로 균일한 컬러맵의 색 지도 |
캡션. 캡션은 그림만 보고 결과를 이해할 수 있게 쓴다. 그림이 말하는 문장, 무엇을 그렸는지(점·선·막대가 각각 무엇인가), 오차 막대가 무엇인지(표준편차인가 신뢰구간인가, 몇 번 반복했는가), 측정 조건을 담는다.
시각화 원칙
축과 단위. 모든 축에는 양의 이름과 단위를 쓴다. RMSE (K), Time (ms), Capacity retention (%). 단위가 없는 양은 무엇으로 정규화했는지 쓴다(Normalized flux (/ flux at t = 0)). 눈금 숫자는 읽을 수 있는 크기로, 필요한 만큼만 둔다.
오차 막대. 오차 막대가 무엇을 나타내는지 밝히지 않은 그림은 해석할 수 없다. 같은 데이터에서도 표준편차(SD), 표준오차(SE), 95% 신뢰구간(CI)의 길이는 크게 다르다. seed 5개로 학습한 두 방법의 RMSE를 본다.
import numpy as np
from scipy import stats
rng = np.random.default_rng(2)
seed_fx = rng.normal(0, 0.03, 5) # seed마다 두 방법 공통 효과, (5,)
rmse_a = 0.42 + seed_fx + rng.normal(0, 0.006, 5) # 온도 예측 RMSE (K), (5,)
rmse_b = 0.40 + seed_fx + rng.normal(0, 0.006, 5)
t4 = stats.t.ppf(0.975, df=4) # 자유도 4의 97.5% 분위수
for name, r in (("A", rmse_a), ("B", rmse_b)):
sd = r.std(ddof=1)
se = sd / np.sqrt(len(r))
print(f"{name}: 평균 {r.mean():.3f} K SD {sd:.3f} SE {se:.3f} 95% CI 반폭 {t4 * se:.3f}")
d = rmse_b - rmse_a # 같은 seed끼리 짝지은 차이, (5,)
half = t4 * d.std(ddof=1) / np.sqrt(len(d))
print(f"짝지은 차이 B − A: {d.mean():+.3f} K, 95% 구간 [{d.mean() - half:+.3f}, {d.mean() + half:+.3f}]")A: 평균 0.413 K SD 0.045 SE 0.020 95% CI 반폭 0.055 B: 평균 0.392 K SD 0.049 SE 0.022 95% CI 반폭 0.061 짝지은 차이 B − A: -0.022 K, 95% 구간 [-0.028, -0.015]
세 가지를 읽을 수 있다.
- 막대의 종류에 따라 길이가 몇 배 다르다. 에서 95% CI 반폭은 SE의 배이고, SE는 SD의 배다. A의 SE 막대(0.020)와 95% CI 막대(0.055)는 같은 데이터에서 나왔다. 캡션에 종류를 쓰지 않으면 독자는 불확실성을 몇 배 잘못 읽는다.
- 막대가 겹친다고 차이가 없는 것은 아니다. A와 B의 95% CI는 크게 겹친다(0.358–0.468과 0.331–0.453). 그러나 같은 seed끼리 짝지은 차이의 구간 [−0.028, −0.015]는 0을 포함하지 않고, 실제로 다섯 seed 모두에서 B가 낫다. seed마다 두 방법이 함께 흔들리는 공통 변동이 크기 때문이다. 짝지은 설계의 결과를 독립 표본처럼 막대 두 개로 그리면 이 정보가 사라진다.
- 그래서 그림은 비교의 구조를 따라야 한다. 짝지은 실험이면 seed별 점을 선으로 잇거나, 차이와 그 구간을 직접 그린다. 아래 "재현 가능한 그림" 절의 두 그림이 그 예다.
축의 범위. 막대는 길이로 값을 나타낸다. 그래서 막대 그래프의 축이 0에서 시작하지 않으면 길이의 비가 값의 비와 달라지고, 작은 차이가 크게 보인다. Tufte(1983)는 이 왜곡을 lie factor로 정의했다.
여기서 효과의 크기는 두 값 사이의 상대 변화율, 예를 들어 다. 왜곡이 없는 그림의 lie factor는 1이다. 정확도 0.912와 0.925를 두 축 범위로 그려 비교한다. 그림은 파일로만 저장하고 수치를 출력한다.
import os
import tempfile
import matplotlib
matplotlib.use("Agg") # 화면 없이 파일로만 그린다
import matplotlib.pyplot as plt
acc = {"A": 0.912, "B": 0.925} # 정확도
def lie_factor(ax, a, b):
y0 = ax.get_ylim()[0] # 막대가 시작하는 축의 아래 끝
shown = ((b - y0) - (a - y0)) / (a - y0) # 그림에서 보이는 변화율
return shown / ((b - a) / a) # ÷ 데이터의 변화율
for tag, ylim in (("truncated", (0.905, 0.93)), ("zero-based", (0.0, 1.0))):
fig, ax = plt.subplots(figsize=(2.5, 2.5))
ax.bar(list(acc), list(acc.values()), color="#0072B2")
ax.set_ylim(*ylim)
ax.set_ylabel("Accuracy")
fig.savefig(os.path.join(tempfile.gettempdir(), f"bars-{tag}.svg"))
plt.close(fig)
print(f"{tag:10s} y축 [{ylim[0]}, {ylim[1]}] lie factor {lie_factor(ax, *acc.values()):.1f}")truncated y축 [0.905, 0.93] lie factor 130.3 zero-based y축 [0.0, 1.0] lie factor 1.0
축을 0.905에서 자르면 B의 막대가 A의 2.9배 높이로 보인다. 실제 차이는 1.4%다. 그림이 효과를 130배 부풀렸다. 그렇다고 0부터 그린 막대가 좋은 그림인 것도 아니다. 두 막대가 거의 같아 보여 차이를 읽을 수 없다. 해법은 형태를 바꾸는 것이다. 점은 길이가 아니라 위치로 값을 나타내므로 축이 0을 포함하지 않아도 된다. 정확도 차이를 말하려면 차이(B − A)와 그 구간을 점과 오차 막대로 그리고, 0에 기준선을 긋는다.
로그 축. 값이 여러 자릿수에 걸치면(격자 크기에 따른 수치 오차 –, 데이터 크기에 따른 학습 시간) 선형 축에서는 작은 값들이 바닥에 눌려 보이지 않는다. 로그 축을 쓰면 비율이 같은 변화가 같은 거리로 보인다. 특히 꼴의 관계는 양쪽 로그 축에서 기울기 인 직선이 된다.
수치해석의 수렴 차수 그림(9부)이 이 성질을 쓴다. 로그 축에서는 0과 음수를 그릴 수 없고, 막대 그래프는 의미가 없어진다(막대의 "길이"가 축의 시작점에 따라 임의로 바뀐다). 축 레이블이나 캡션에 로그 축임을 밝히고, 눈금은 , 처럼 10의 거듭제곱으로 둔다.
색. 색은 범주를 구별하거나(질적 팔레트) 크기를 나타낸다(연속 컬러맵). 연속 컬러맵에서 크기를 읽는 주된 단서는 밝기다. 값이 커질 때 밝기가 단조롭게 바뀌지 않으면, 데이터에 없는 경계가 보이거나 실제 경계가 사라진다. 무지개(rainbow) 계열 컬러맵인 jet이 대표적인 예이고, Crameri 외(2020)는 이런 컬러맵이 데이터를 시각적으로 왜곡하고 색각 이상이 있는 독자에게 읽히지 않는다는 점을 들어 과학 그림에서 쓰지 말 것을 권했다. 컬러맵 세 개의 밝기를 CIELAB 색공간의 (0 = 검정, 100 = 흰색)로 잰다.
def lightness(rgb): # sRGB (N, 3), 0–1 → CIELAB L* (N,)
lin = np.where(rgb <= 0.04045, rgb / 12.92, ((rgb + 0.055) / 1.055) ** 2.4)
Y = lin @ np.array([0.2126, 0.7152, 0.0722]) # 상대 휘도, (N,)
return np.where(Y > (6 / 29) ** 3, 116 * np.cbrt(Y) - 16, Y * (29 / 3) ** 3)
x = np.linspace(0, 1, 256)
for name in ("jet", "viridis", "gray"):
cmap = matplotlib.colormaps[name]
L = lightness(cmap(x)[:, :3]) # (256,)
up = np.diff(L) > 0.01
print(f"{name:8s} L* {L[0]:5.1f} → {L[-1]:5.1f} 최대 L* 위치 {x[L.argmax()]:.2f}"
f" 단조 증가 {bool(up.all())}")
okabe_ito = {"orange": "#E69F00", "sky blue": "#56B4E9", "bluish green": "#009E73", "yellow": "#F0E442",
"blue": "#0072B2", "vermillion": "#D55E00", "reddish purple": "#CC79A7"}
rgb = np.array([[int(h[i:i + 2], 16) / 255 for i in (1, 3, 5)] for h in okabe_ito.values()]) # (7, 3)
for k, v in sorted(zip(okabe_ito, lightness(rgb)), key=lambda kv: kv[1]):
print(f" {k:14s} L* {v:5.1f}")jet L* 12.9 → 25.4 최대 L* 위치 0.64 단조 증가 False viridis L* 14.9 → 90.9 최대 L* 위치 1.00 단조 증가 True gray L* 0.0 → 100.0 최대 L* 위치 1.00 단조 증가 True blue L* 46.0 vermillion L* 54.2 bluish green L* 57.7 reddish purple L* 61.0 sky blue L* 69.8 orange L* 70.6 yellow L* 89.1
jet은 양 끝의 밝기가 비슷하게 어둡고(12.9, 25.4) 가장 밝은 곳이 값의 64% 지점(노란색 부근)이다. 흑백으로 인쇄하면 가장 작은 값과 가장 큰 값이 비슷한 회색이 되고, 중간의 노란 띠가 데이터에 없는 경계처럼 보인다. viridis는 밝기가 처음부터 끝까지 단조롭게 증가하므로 흑백에서도 순서가 보존된다. matplotlib의 기본 컬러맵이 viridis인 이유다(집필 시점, matplotlib 2.0부터).
범주를 구별하는 팔레트에서는 색각 이상을 고려한다. Okabe와 Ito가 제안한 8색 팔레트(위 7색과 검정)는 흔한 색각 이상에서도 서로 구별되도록 고른 색이다. 그러나 위 출력이 보이듯 orange와 sky blue는 밝기가 거의 같다(70.6, 69.8). 흑백으로 인쇄하면 두 색은 같은 회색이 된다. 그래서 색만으로 범주를 구별하지 않고 marker 모양이나 선 종류를 함께 바꾼다. 빨강과 초록만으로 "좋음/나쁨"을 구별하는 그림은 적록 색각 이상이 있는 독자에게 읽히지 않는다.
도구
matplotlib 스타일 설정. 그림마다 글꼴 크기와 선 굵기를 따로 정하면 논문 안에서 그림들이 제각각이 된다. 스타일을 한곳에 정의하고 모든 그림 스크립트가 같은 설정을 쓰게 한다. 실습 스크립트 labs/research-practice/figures-and-tables/make_figures.py의 설정은 다음과 같다(값은 집필 시점 예시, 투고처 템플릿에서 확인).
STYLE = {
"figure.figsize": (3.25, 2.2), # 2단 논문의 한 단 폭(인치) — 템플릿에서 확인
"font.size": 8, "axes.labelsize": 8, "legend.fontsize": 7,
"xtick.labelsize": 7, "ytick.labelsize": 7,
"axes.spines.top": False, "axes.spines.right": False,
"pdf.fonttype": 42, # 글꼴을 TrueType으로 넣어 텍스트로 남긴다
"savefig.bbox": "tight",
}
with plt.rc_context(STYLE):
... # 모든 그림을 이 블록 안에서 그린다
크기와 글꼴. 그림은 최종 인쇄 크기로 만든다. 큰 그림을 만들어 논문에서 줄이면 글자가 본문보다 훨씬 작아진다. 한 단 폭(2단 논문에서 대략 3.25–3.5인치, 템플릿마다 다름)으로 그리고 글꼴을 본문 크기에 가깝게(7–9 pt) 둔다. 그림 속 글자가 본문 캡션보다 작으면 읽히지 않는다.
벡터 형식. 선과 글자로 이루어진 그림은 PDF·SVG 같은 벡터 형식으로 저장한다. 확대해도 깨지지 않고, 파일이 작고, 글자를 검색할 수 있다. 수백만 개의 점이나 큰 이미지(현미경 사진, 위성 영상)는 PNG 같은 래스터 형식이 더 작고 빠르며, 해상도는 투고처가 요구하는 값(흔히 300 dpi 이상)으로 맞춘다. 벡터 그림 안의 일부만 래스터로 넣는 방법(rasterized=True)도 있다.
재현 가능한 그림
왜 필요한가. 논문 마감 직전에 버그를 고쳐 결과가 바뀌거나, 리뷰어가 축을 바꿔 달라고 하거나, 공동 저자가 색을 통일하자고 하면 그림을 다시 만들어야 한다. 그림을 손으로 편집했다면(그래픽 편집기에서 레이블을 고치거나 점을 옮겼다면) 그 작업을 처음부터 다시 해야 하고, 그 과정에서 숫자와 그림이 어긋난다.
정의. 재현 가능한 그림 파이프라인은 다음을 만족한다.
- 결과 파일에서 시작한다. 그림 스크립트는 실험을 다시 돌리지 않고, 실험이 남긴 결과 파일(CSV, JSON 등)만 읽는다. 결과 파일에는 run ID와 커밋이 연결되어 있다(23.7장, 22.1장).
- 명령 하나로 모든 그림과 표를 만든다.
make_figures.py하나, 또는make figures같은 대상 하나. - 손으로 고치지 않는다. 레이블·색·범례는 모두 코드에서 정한다. 손으로 고칠 일이 생기면 코드를 고친다.
- 같은 입력이면 같은 출력. 날짜 같은 메타데이터를 파일에 넣지 않으면, 결과가 바뀌지 않았을 때 그림 파일도 바뀌지 않는다. 그림이 바뀌었다면 결과가 바뀐 것이다.
코드. 실습 스크립트는 results/runs.csv(seed 5개 × 방법 2개 × 시험 온도 3개)를 읽어 그림 두 개와 LaTeX 표 하나를 만든다. 첫 그림은 seed별 점을 같은 seed끼리 선으로 이은 그림, 둘째 그림은 짝지은 차이 B − A와 95% 구간을 0 기준선과 함께 그린 그림이다. 스크립트는 같은 출력을 두 번 만들어 hash를 비교한다. 집필 시점의 실행 결과는 다음과 같다(hash는 matplotlib 버전에 따라 다를 수 있다).
fig-gap-by-temp.pdf sha256:e387f20e456b 다시 만들어도 같음: True
fig-paired-seeds.pdf sha256:8467fb7ae8de 다시 만들어도 같음: True
tab-per-temp.tex sha256:366e85e22447 다시 만들어도 같음: True
\begin{tabular}{lccc}
\toprule
Temp. & A (K) & B (K) & B $-$ A (K), 95\% CI \\
\midrule
0\,°C & $0.620 \pm 0.031$ & $0.664 \pm 0.031$ & $\mathbf{+0.044\ [+0.035, +0.053]}$ \\
25\,°C & $0.411 \pm 0.034$ & $0.372 \pm 0.022$ & $\mathbf{-0.039\ [-0.055, -0.022]}$ \\
45\,°C & $0.474 \pm 0.035$ & $0.435 \pm 0.030$ & $\mathbf{-0.039\ [-0.053, -0.025]}$ \\
\bottomrule
\end{tabular}
PDF를 저장할 때 metadata={"CreationDate": None}으로 생성 날짜를 빼서, 같은 입력에서 같은 바이트가 나온다. 표의 숫자도 스크립트가 쓰므로, 결과 파일이 바뀌면 그림과 표가 함께 바뀐다. 손으로 옮긴 숫자가 그림과 어긋나는 일이 생기지 않는다. 논문 원고는 outputs/의 파일을 \includegraphics와 \input으로 읽는다.
연구에서의 의미. 그림 스크립트는 논문의 일부로 저장소에 남긴다. 공개 코드에 그림 스크립트와 결과 파일이 있으면, 독자는 그림의 모든 점이 어떤 run에서 왔는지 확인할 수 있다. 이것은 재현성(22.2장)의 마지막 단계다. 실험을 다시 돌릴 수 없는 독자도 결과 파일에서 그림까지의 경로는 검증할 수 있다.
표
언제 표를 쓰는가. 독자가 정확한 숫자를 읽고 비교해야 하면 표, 추세나 패턴을 봐야 하면 그림이다. 여러 방법 × 여러 데이터셋의 주 결과는 보통 표로, 학습 곡선이나 조건에 따른 변화는 그림으로 보인다.
정렬. 숫자 열은 오른쪽 또는 소수점으로 정렬해 자릿수를 눈으로 비교할 수 있게 한다. 텍스트 열은 왼쪽 정렬한다. 세로선 없이 가로선 몇 개로 구분하는 형식(LaTeX booktabs)이 읽기 쉽다(23.8장). 단위는 셀마다 쓰지 않고 열 머리에 한 번 쓴다.
유효숫자. 표의 숫자는 불확실성이 허락하는 자릿수까지만 쓴다. 표준편차가 0.045인 값을 0.41327814로 쓰면 소수 셋째 자리부터는 잡음이다. 흔한 규칙은 불확실성을 유효숫자 1–2자리로 반올림하고, 평균을 그 마지막 자리와 같은 자릿수까지 쓰는 것이다.
def fmt(mean, err, sig=2):
dec = max(sig - 1 - int(np.floor(np.log10(err))), 0) # err의 유효숫자 sig개가 남는 소수 자릿수
return f"{mean:.{dec}f} ± {err:.{dec}f}"
time_ms = rng.lognormal(np.log(12), 0.15, 5) # 추론 시간 (ms), (5,)
rows = {"A": (rmse_a, time_ms * 0.8), "B": (rmse_b, time_ms)}
for name, (r, t) in rows.items():
raw = f"{r.mean():.8f} ± {r.std(ddof=1):.8f}"
print(f"{name} RMSE 그대로 {raw} → {fmt(r.mean(), r.std(ddof=1))} K"
f" 추론 시간 {fmt(t.mean(), t.std(ddof=1))} ms")A RMSE 그대로 0.41325281 ± 0.04468845 → 0.413 ± 0.045 K 추론 시간 9.36 ± 0.80 ms B RMSE 그대로 0.39167009 ± 0.04899274 → 0.392 ± 0.049 K 추론 시간 11.7 ± 1.0 ms
추론 시간 열에서 A는 소수 둘째 자리(9.36 ± 0.80), B는 첫째 자리(11.7 ± 1.0)까지 쓴다. 불확실성의 크기가 다르기 때문이다. 같은 열 안에서 자릿수가 달라 보기 불편하면 열 전체를 더 큰 불확실성에 맞춰 반올림할 수 있다(정보를 조금 버리는 쪽이다). 반대로 불확실성보다 많은 자릿수를 쓰는 것은 정보가 아니라 잡음이다. 위의 fmt는 반올림이 자릿수를 올리는 경우(0.0996 → 0.1)를 처리하지 않는다. 연습문제에서 그 경우까지 다룬다.
강조 규칙. 결과 표에서 "가장 좋은 값"을 굵게 쓰는 관행은 차이가 변동성보다 작을 때 운을 강조한다(12.5장). 강조에는 규칙을 정하고 캡션에 쓴다. 예를 들어 "짝지은 95% 구간이 0을 포함하지 않는 경우만 굵게"처럼 쓴다. 위 실습 스크립트의 표가 이 규칙을 코드로 구현한다.
실습
논문 그림 전체를 결과 파일에서 한 번에 다시 생성하는 스크립트를 만든다.
labs/research-practice/figures-and-tables/의simulate_runs.py와make_figures.py를 실행해 구조를 확인한다. 자신의 연구라면 실험 스크립트가 쓰는 결과 파일 형식을 정한다(run ID, 커밋, 설정 hash 열 포함).- 23.6장의 주장–근거 표(또는 23.8장의 주장 목록)에서 주장마다 그림이 말할 문장을 한 줄로 쓰고, 그 문장에 맞는 형태(짝지은 점, 차이와 구간, 로그 축 선 그래프 등)를 고른다.
- 스타일 설정 하나를 정의하고, 모든 그림을 최종 인쇄 크기·벡터 형식·Okabe–Ito 계열 색과 marker 조합으로 만든다. 연속 값의 색 지도에는 밝기가 단조로운 컬러맵을 쓴다.
- 결과 표를 스크립트가 직접 LaTeX로 쓰게 한다. 유효숫자는 불확실성에 맞추고(아래 연습문제의 함수), 강조 규칙을 코드로 구현한다.
outputs/를 지우고 명령 하나로 모든 그림과 표가 다시 만들어지는지, 두 번 만들었을 때 파일 hash가 같은지 확인한다.- 그림을 흑백으로 인쇄하거나 흑백으로 변환해 보고, 범주와 순서가 여전히 구별되는지 확인한다.
이어서 연습문제를 푼다. 불확실성에 맞춰 반올림하는 함수를 경계 사례까지 구현한다.
실패 사례
- 손으로 편집한 그림. 결과가 바뀌면 다시 만들 수 없고, 숫자와 그림이 어긋난다. 레이블 하나라도 코드에서 고친다.
- 오차 막대가 무엇인지 밝히지 않는 것. SD, SE, 95% CI는 에서 길이가 몇 배 다르다. 캡션에 종류와 반복 수를 쓴다.
- 막대 그래프의 축을 잘라 차이를 부풀리는 것. 이 장의 예에서 lie factor는 130이었다. 차이를 보여 주려면 차이 자체를 점과 구간으로 그린다.
- 무지개 컬러맵. 밝기가 단조롭지 않아 없는 경계를 만들고, 흑백 인쇄와 색각 이상에서 순서가 사라진다.
- 색만으로 범주를 구별하는 것. 색각 이상 친화 팔레트도 밝기가 같은 쌍이 있다. marker 모양이나 선 종류를 함께 쓴다.
- 불확실성보다 많은 자릿수. 0.41327814 ± 0.045는 정밀해 보이지만 정보가 아니다.
통과 기준
- 그림마다 그림이 말하는 문장 하나를 캡션 첫 문장으로 쓰고, 그림만 보고 그 문장을 확인할 수 있는 figure 세트를 만든다. 모든 축에 양과 단위가, 모든 오차 막대에 종류와 반복 수가 있다.
- 결과 파일에서 명령 하나로 모든 그림과 표가 다시 만들어지고, 두 번 만들었을 때 출력 파일이 같다.
- 연습문제
uncertainty-rounding의 테스트를 통과한다.
참고 문헌
- Tufte (1983). The Visual Display of Quantitative Information. Graphics Press. — lie factor, 데이터 대비 잉크 등 정량 그래픽의 원칙
- Rougier, Droettboom, Bourne (2014). Ten simple rules for better figures. PLoS Computational Biology, 10(9), e1003833. — 메시지·매체·캡션·색·기본값에 대한 실용 규칙
- Crameri, Shephard, Heron (2020). The misuse of colour in science communication. Nature Communications, 11, 5444. — 무지개·적록 컬러맵의 문제와 과학적으로 설계된 컬러맵