Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

วิธีทำให้ Legend Keys หลายอันชี้ไปยัง Entry เดียวใน Matplotlib

เมื่อต้องการให้ Legend Key หลายรูปแบบ (เช่น เส้นและจุด) แสดงใน Legend Entry เดียวกัน ใช้ HandlerTuple จาก matplotlib.legend_handler ร่วมกับการจัดกลุ่ม Artist เป็น Tuple

หลักการ

  1. Plot เส้น/จุดแยกกันได้ Artist หลายตัว
  2. จัดกลุ่ม Artist ที่ต้องการให้อยู่ Entry เดียวเป็น Tuple: (artist1, artist2)
  3. ใช้ handler_map={tuple: HandlerTuple(ndivide=None)} เพื่อบอก Legend ให้วาด Key ทั้งคู่ใน Entry เดียว

ตัวอย่างโค้ด

import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerTuple

plt.rcParams["figure.figsize"] = [10, 6]
plt.rcParams["figure.autolayout"] = True

# สร้างข้อมูล
x = np.linspace(0, 10, 50)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots()

# Plot 2 เส้น แยก Artist
line1, = ax.plot(x, y1, 'r-', linewidth=2, label='_nolegend_')
line2, = ax.plot(x, y2, 'b--', linewidth=2, label='_nolegend_')

# Plot จุดสำหรับ Legend (Optional)
scatter1 = ax.scatter(x[::5], y1[::5], c='r', s=50, zorder=5, label='_nolegend_')
scatter2 = ax.scatter(x[::5], y2[::5], c='b', s=50, marker='s', zorder=5, label='_nolegend_')

# สร้าง Legend: จัดกลุ่ม (line1, scatter1) และ (line2, scatter2) เป็น Entry เดียว
legend = ax.legend(
    [(line1, scatter1), (line2, scatter2)],  # List of Tuples
    ['Sine Wave (sin)', 'Cosine Wave (cos)'],
    handler_map={tuple: HandlerTuple(ndivide=None)},  # สำคัญ!
    loc='upper right',
    fontsize=12,
    framealpha=0.9
)

ax.set_xlabel('X', fontsize=12)
ax.set_ylabel('Y', fontsize=12)
ax.set_title('Multiple Legend Keys per Entry', fontsize=14)
ax.grid(True, alpha=0.3)

plt.show()

ผลลัพธ์

Legend แสดง 2 Entry แต่ละ Entry มี Key 2 อัน: เส้น + จุด (Circle สำหรับ Sine, Square สำหรับ Cosine) แสดงในแถวเดียวกัน

ตัวเลือก HandlerTuple

  • ndivide=None: วาด Key ทั้งหมดในพื้นที่เดียว (Default)
  • ndivide=2: แบ่งพื้นที่ Key เป็น 2 ส่วน (วาดซ้อนกันไม่ได้)
  • pad: ระยะห่างระหว่าง Keys

วิธีอื่น: ใช้ HandlerLine2D สำหรับเส้นหลายสไตล์

from matplotlib.legend_handler import HandlerLine2D

# สร้างเส้นเดียวแต่มีสไตล์หลายอย่าง (Dash + Solid)
line, = ax.plot(x, y1, 'r-', linewidth=2)
line.set_dashes([5, 2, 1, 2])  # Custom dash pattern

# Handler แสดงหลายสไตล์ใน Key เดียว
class MultiStyleHandler(HandlerLine2D):
    def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans):
        return super().create_artists(legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans)

# ใช้งาน
ax.legend([line], ['Multi-style Line'], handler_map={line: MultiStyleHandler()})

คำแนะนำ

  • ใช้ label='_nolegend_' เพื่อไม่ให้ Artist ตัวนั้นปรากฏใน Legend อัตโนมัติ
  • HandlerTuple เหมาะสำหรับรวม Marker + Line, หรือ Line + Fill
  • สำหรับกรณีซับซ้อน ให้สร้าง Custom Handler โดยสืบทอดจาก HandlerBase