HocThuatSo.comHọc Thuật Số
Gửi thư
Trực quan hoá dữ liệu khoa học

matplotlib cho hình khoa học: cỡ hình đúng cột, phông chữ nhất quán

Đặt cỡ hình matplotlib theo inch của cột tạp chí, gom thiết lập vào tệp kiểu .mplstyle, chọn phông có dấu tiếng Việt, nhúng phông khi xuất PDF và SVG, tránh bbox tight làm lệch kích thước.

matplotlib cho hình khoa học: cỡ hình đúng cột, phông chữ nhất quán

Để hình matplotlib đúng chuẩn tạp chí, đặt figsize bằng inch theo bề rộng cột (đổi từ milimét bằng cách chia 25,4), gom cỡ chữ và kiểu đường vào một tệp .mplstyle dùng chung, chọn phông có đủ dấu tiếng Việt, và xuất PDF với pdf.fonttype: 42 để phông được nhúng dạng TrueType.

matplotlib mặc định hình 6,4 × 4,8 inch, chữ 10 pt, phù hợp xem trên màn hình nhưng không khớp cột tạp chí nào. Chỉnh tay từng hình vừa mất công vừa làm các hình trong cùng bài lệch nhau. Mã trong bài đã chạy với matplotlib 3.11.

Kích thước hình theo cột

Đổi milimét sang inch

figsize nhận inch. Khai một hằng số MM = 1 / 25.4 rồi viết fig, ax = plt.subplots(figsize=(85 * MM, 60 * MM), layout='constrained') cho hình một cột rộng 85 mm, hay (174 * MM, 70 * MM) cho hình hai cột. Lấy bề rộng chính xác từ hướng dẫn tác giả của tạp chí.

Bố cục constrained

layout='constrained' tự co giãn khoảng trống giữa các trục để nhãn không đè nhau mà vẫn giữ kích thước hình. Cách cũ plt.tight_layout() cũng chạy, nhưng constrained xử lý tốt hơn khi có thanh màu và chú giải chung.

Cẩn thận với bbox tight

Lưu với bbox_inches='tight' cắt hoặc nới viền theo nội dung, nên hình lưu ra không còn đúng kích thước bạn khai. Khi chạy thử, một hình khai rộng 85 mm, lưu ở 300 DPI, không dùng tight cho 1.003 điểm ảnh bề ngang, đúng như tính toán; dùng tight cho 1.038 điểm ảnh, tức rộng hơn khoảng 3 mm. Với hình cần đúng cột, dùng bố cục constrained và bỏ tight.

DPI màn hình và DPI khi lưu

figure.dpi chỉ ảnh hưởng tới hình hiển thị trong sổ tay hay cửa sổ; savefig.dpi mới quyết định số điểm ảnh của tệp PNG, TIFF. Hình hiện trên màn hình to hay nhỏ không nói gì về cỡ in. Muốn xem trước đúng cỡ in, mở tệp PDF đã lưu ở mức thu phóng 100% với kích thước vật lý, hoặc in thử một trang.

Tệp kiểu .mplstyle: thiết lập một lần

Tệp kiểu là tệp chữ thuần, mỗi dòng một tham số dạng tên: giá trị. Một tệp bai-bao.mplstyle gọn gồm: font.size: 8, axes.labelsize: 8, xtick.labelsize: 7, ytick.labelsize: 7, legend.fontsize: 7, axes.spines.top: False, axes.spines.right: False, lines.linewidth: 1.0, savefig.dpi: 600, pdf.fonttype: 42, ps.fonttype: 42, svg.fonttype: none.

Nạp ở đầu mọi kịch bản vẽ bằng plt.style.use('bai-bao.mplstyle'), đường dẫn tính từ thư mục chạy. Có thể chồng nhiều kiểu: plt.style.use(['seaborn-v0_8-colorblind', 'bai-bao.mplstyle']), kiểu sau ghi đè kiểu trước. Danh sách kiểu có sẵn xem bằng plt.style.available; bản 3.11 có cả tableau-colorblind10 và petroff10 với chu trình màu thân thiện với người mù màu.

Muốn đổi tạm cho một hình, dùng khối with plt.rc_context({'font.size': 7}): thay vì sửa rcParams toàn cục, để các hình sau không bị ảnh hưởng.

Phông chữ có dấu tiếng Việt

Phông mặc định

Phông mặc định của matplotlib là DejaVu Sans, có đủ chữ tiếng Việt. Khi thử xuất hình có nhãn “Thời gian (tuần)”, “Điểm đánh giá”, chữ hiện đúng và pdffonts báo phông DejaVu Sans được nhúng.

Đổi sang phông tạp chí yêu cầu

Khai font.family: serif và font.serif: Times New Roman (hoặc phông khác) trong tệp kiểu. Phông phải được cài trên máy; matplotlib dựng danh sách phông khi chạy lần đầu, nên sau khi cài phông mới có thể cần xoá bộ nhớ đệm phông trong thư mục cấu hình của matplotlib để nó nhận ra.

Nhận biết khi phông không tìm thấy

matplotlib không dừng, chỉ in cảnh báo dạng findfont: Font family [...] not found. Falling back to DejaVu Sans. rồi vẽ bằng phông mặc định. Đọc kỹ đầu ra khi chạy: một bài có hình dùng hai phông khác nhau thường bắt đầu từ cảnh báo bị bỏ qua này. Phông thiếu một vài chữ có dấu thì matplotlib cũng cảnh báo thiếu ký tự và chữ đó hiện thành ô trống.

Xuất vector và ảnh điểm

Các lệnh đã chạy thử với hình hai khung rộng 174 mm:

Mục đíchLệnhGhi chú
PDF vectorfig.savefig('hinh.pdf')Với pdf.fonttype: 42, phông nhúng dạng TrueType
SVG giữ chữfig.savefig('hinh.svg')Với svg.fonttype: none, chữ là chữ, chỉnh được trong phần mềm đồ hoạ
TIFF cho tạp chífig.savefig('hinh.tiff', dpi=600, pil_kwargs={'compression': 'tiff_lzw'})Nén LZW không mất dữ liệu
PNG xem nhanhfig.savefig('hinh.png', dpi=300)Cho bản thảo, trình chiếu
Hình rất nhiều điểmax.scatter(..., rasterized=True) rồi lưu PDFLớp điểm thành ảnh điểm, trục và chữ vẫn vector

Một hình mẫu từ đầu đến cuối

Đoạn mã đã chạy thử cho hình hai khung: nạp kiểu bằng plt.style.use('bai-bao.mplstyle'); tạo hình fig, axs = plt.subplots(1, 2, figsize=(174 * MM, 70 * MM), layout='constrained'); khung trái vẽ đường axs[0].plot(x, y, label='Nhóm thực nghiệm') kèm axs[0].set_xlabel('Thời gian (tuần)') và axs[0].legend(frameon=False); khung phải vẽ điểm axs[1].scatter(x, z, s=6, c=x, cmap='viridis') kèm axs[1].set_ylabel('Điểm đánh giá').

Lưu cùng lúc ba định dạng: fig.savefig('hinh.pdf'), fig.savefig('hinh.tiff', dpi=600, pil_kwargs={'compression': 'tiff_lzw'}), fig.savefig('hinh.svg'). Kiểm tệp PDF bằng pdffonts hinh.pdf: với tệp kiểu ở trên, cả DejaVu Sans thường và đậm đều được nhúng, kiểu CID TrueType.

Bỏ plt.show() trong kịch bản chạy nền; trong sổ tay Jupyter, hình tự hiện ở cuối ô. Đóng hình bằng plt.close(fig) khi vẽ nhiều hình trong vòng lặp để không tốn bộ nhớ.

Định dạng số kiểu Việt Nam trên trục

matplotlib mặc định dùng dấu chấm thập phân và không phân cách hàng nghìn. Bài tiếng Việt cần dấu chấm hàng nghìn và dấu phẩy thập phân thì dùng bộ định dạng tự viết: from matplotlib.ticker import FuncFormatter, rồi ax.yaxis.set_major_formatter(FuncFormatter(lambda v, pos: f'{v:,.0f}'.replace(',', '.'))). Khi chạy thử, các vạch hiện “800”, “1.000”, “1.200”. Với số thập phân, đổi chuỗi định dạng và hoán đổi hai dấu cẩn thận.

Cách khác là bật axes.formatter.use_locale và đặt ngôn ngữ hệ thống sang tiếng Việt, nhưng kết quả phụ thuộc cấu hình máy, khó lặp lại trên máy người khác. Bộ định dạng tự viết trong mã đáng tin hơn.

Màu và chu trình màu

Màu của các đường vẽ lần lượt lấy từ chu trình axes.prop_cycle. Đặt chu trình trong tệp kiểu để mọi hình dùng cùng một bộ màu an toàn, ví dụ các mã màu của bảng Okabe–Ito, hoặc dùng sẵn kiểu petroff10. Với dữ liệu liên tục, giữ viridis hay cividis; với dữ liệu lệch hai phía quanh 0, dùng bảng phân kỳ như RdBu kèm chuẩn hoá căn giữa.

Kết hợp màu với kiểu điểm (marker) và kiểu đường (linestyle) để hình vẫn đọc được khi in đen trắng.

Nhiều khung, nhãn A B C và chú giải chung

fig, axs = plt.subplots(1, 2, figsize=(174 * MM, 70 * MM), layout='constrained') cho hai trục cạnh nhau. Đánh nhãn khung đơn giản bằng tiêu đề căn trái: for ax, t in zip(axs, 'AB'): ax.set_title(t, loc='left', fontweight='bold'). Bố cục phức tạp hơn dùng fig.subplot_mosaic('AAB;CCB'), mỗi chữ cái là một khung, trả về từ điển trục theo tên.

Chú giải chung cho cả hình: fig.legend(handles, labels, loc='outside lower center', ncols=3); vị trí bắt đầu bằng outside hoạt động với bố cục constrained. Khi các khung cần so sánh, khai sharey=True trong subplots để dùng chung trục tung.

Lỗi hay gặp

  • Dùng plt.savefig() sau plt.show() trong kịch bản: hình đã bị đóng, tệp lưu ra trống. Lưu trước khi hiển thị, hoặc gọi fig.savefig() trên đối tượng hình.
  • Đặt figsize lớn rồi tăng cỡ chữ cho dễ đọc trên màn hình; khi tạp chí thu nhỏ về một cột, chữ quá bé.
  • Để phông kiểu Type 3 trong PDF; một số hệ thống nộp bài và phần mềm biên tập không xử lý tốt. Đặt pdf.fonttype: 42.
  • Dùng bảng màu cầu vồng jet cho dữ liệu liên tục; viridis là mặc định vì lý do chính đáng.
  • Chép thiết lập rcParams rải rác vào từng sổ tay; gom về một tệp kiểu.
  • Đặt nhãn khung A, B bằng chữ thường trong khi tạp chí yêu cầu chữ hoa đậm, hoặc ngược lại; đọc quy ước của tạp chí rồi đặt một lần trong hàm vẽ dùng chung cho mọi hình.
  • Hình có nền trong suốt khi lưu PNG với transparent=True, hiện tốt trên trang trắng nhưng thành nền đen ở một số trình xem; với tệp nộp tạp chí, để nền trắng.

Câu hỏi thường gặp

Nên dùng giao diện pyplot hay giao diện hướng đối tượng?

Với hình bài báo, giao diện hướng đối tượng qua fig và ax rõ ràng hơn: biết chính xác đang vẽ lên trục nào, nhất là khi có nhiều khung. pyplot tiện cho thăm dò nhanh.

seaborn có dùng chung được tệp kiểu không?

Được. seaborn vẽ trên nền matplotlib nên các tham số trong tệp kiểu vẫn áp dụng. Lưu ý một số hàm của seaborn tự đặt chủ đề riêng; gọi plt.style.use sau khi nạp seaborn để thiết lập của bạn được ưu tiên.

Làm sao biết phông nào matplotlib đang dùng?

Gọi matplotlib.font_manager.findfont với tên phông, hàm trả đường dẫn tệp phông thật sự được chọn. Nếu trả về DejaVu Sans trong khi bạn khai phông khác, nghĩa là phông chưa được tìm thấy.

Có nên vẽ biểu đồ bằng Excel rồi chỉnh trong phần mềm đồ hoạ?

Được với hình đơn lẻ, nhưng khó lặp lại khi dữ liệu đổi. Vẽ bằng mã giúp mỗi lần sửa dữ liệu chỉ cần chạy lại, hình luôn khớp với số liệu.

Hình SVG có nộp tạp chí được không?

Tuỳ tạp chí; nhiều nơi nhận PDF hoặc EPS hơn SVG. SVG hữu ích khi cần chỉnh chi tiết trong phần mềm đồ hoạ trước khi xuất sang định dạng tạp chí yêu cầu.

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

🧭
Bạn đang ở chặng nào của đường học vị?
Nhập chỗ bạn đang đứng và đích bạn nhắm — công cụ trả về số năm, chi phí và việc phải làm từng chặng.
Xem lộ trình của tôi →
Miễn phí, không cần tài khoản. Xem tất cả công cụ

Bạn cần hỗ trợ thêm?

Để lại thông tin, chúng tôi sẽ liên hệ trong 24 giờ.

hoặc
[email protected]