آموزش Matplotlib؛ رسم نمودار حرفهای با پایتون از صفر تا ساخت داشبورد
در این آموزش جامع Matplotlib، رسم انواع نمودار با پایتون، ساخت داشبورد، نمایش صحیح متن فارسی، ذخیره خروجی PNG و SVG و ترکیب مصورسازی داده با هوش مصنوعی درواره را بهصورت عملی یاد میگیرید.
دادههای خام، حتی اگر دقیق و ارزشمند باشند، همیشه قابل فهم نیستند. یک فایل CSV با هزاران ردیف فروش، گزارش عملکرد یک مدل یادگیری ماشین یا خروجی یک API ممکن است اطلاعات مهمی داشته باشد؛ اما پیدا کردن روندها، نقاط غیرعادی و روابط موجود در آن بدون نمودار دشوار است.
کتابخانه Matplotlib یکی از مهمترین ابزارهای مصورسازی داده در پایتون است. با استفاده از آن میتوان نمودارهای خطی، میلهای، پراکندگی، هیستوگرام، نمودارهای چندبخشی، داشبوردهای آماری و تصاویر مناسب گزارش، مقاله و وبسایت تولید کرد.
در این آموزش، Matplotlib را فقط در حد چند دستور ساده بررسی نمیکنیم. هدف این است که پس از مطالعه مقاله بتوانید:
- انواع نمودار را متناسب با مسئله انتخاب کنید
- نمودارهای خوانا و حرفهای بسازید
- دادههای Pandas و NumPy را رسم کنید
- چند نمودار را در یک داشبورد قرار دهید
- متن فارسی را بهدرستی نمایش دهید
- نمودار را با کیفیت مناسب در قالب PNG، SVG یا PDF ذخیره کنید
- نمودار را در برنامههای تحت وب و API استفاده کنید
- خلاصه داده را برای تحلیل متنی به هوش مصنوعی درواره ارسال کنید
Matplotlib چیست؟
Matplotlib یک کتابخانه متنباز پایتون برای رسم نمودار و مصورسازی داده است. این کتابخانه در تحلیل داده، آمار، علوم داده، یادگیری ماشین، تحقیقات دانشگاهی و ساخت گزارشهای خودکار کاربرد دارد.
بسیاری از کتابخانههای سطح بالاتر مصورسازی پایتون نیز مستقیم یا غیرمستقیم بر پایه Matplotlib کار میکنند. بنابراین یادگیری آن فقط برای رسم چند نمودار ساده نیست؛ بلکه به شما کمک میکند ساختار داخلی نمودارهای پایتون را بهتر درک کنید.
کاربردهای متداول Matplotlib عبارتاند از:
- رسم روند فروش، درآمد یا تعداد کاربران
- نمایش توزیع دادهها
- مقایسه گروهها و دستهبندیها
- بررسی رابطه بین متغیرها
- نمایش نتایج مدلهای یادگیری ماشین
- ترسیم Loss و Accuracy هنگام آموزش مدل
- ساخت نمودار برای گزارش مدیریتی
- تولید خودکار نمودار در سرور
- ذخیره نمودار برای مقاله، پایاننامه یا شبکههای اجتماعی
تفاوت Figure، Axes و Axis در Matplotlib
درک این سه مفهوم، مهمترین بخش یادگیری اصولی Matplotlib است.
Figure
Figure کل تصویر یا بوم اصلی نمودار است. یک Figure میتواند یک یا چند نمودار داشته باشد.
Axes
Axes ناحیهای از Figure است که داده در آن رسم میشود. اگر یک داشبورد شامل چهار نمودار داشته باشید، معمولاً یک Figure و چهار Axes دارید.
Axis
Axis محور عددی یا دستهبندی نمودار است؛ مانند محور افقی X یا محور عمودی Y.
در راهنمای رسمی Matplotlib، استفاده از رابط شیءگرا یا Object-Oriented برای نمودارهای پیچیده و کدهای قابل استفاده مجدد پیشنهاد شده است. به همین دلیل در بیشتر مثالهای این مقاله از fig و ax استفاده میکنیم.
نصب Matplotlib
ابتدا یک محیط مجازی برای پروژه بسازید:
python -m venv .venv
فعالسازی در ویندوز:
.venv\Scripts\activate
فعالسازی در Linux یا macOS:
source .venv/bin/activate
سپس کتابخانههای موردنیاز را نصب کنید:
pip install matplotlib numpy pandas
اگر میخواهید متن فارسی را با جهت و اتصال صحیح حروف نمایش دهید، این دو بسته را نیز نصب کنید:
pip install arabic-reshaper python-bidi
برای بررسی نصب Matplotlib:
python -c "import matplotlib; print(matplotlib.__version__)"
اولین نمودار با Matplotlib
مثال زیر یک نمودار ساده از میزان فروش ماهانه ایجاد میکند:
import matplotlib.pyplot as plt
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
sales = [120, 145, 138, 172, 190, 215]
fig, ax = plt.subplots(figsize=(10, 5), layout="constrained")
ax.plot(
months,
sales,
marker="o",
linewidth=2.5,
color="#6C4DF6"
)
ax.set_title("Monthly Sales")
ax.set_xlabel("Month")
ax.set_ylabel("Sales")
ax.grid(axis="y", alpha=0.25)
plt.show()
دستور plt.subplots() همزمان یک Figure و یک Axes میسازد.
پارامتر figsize اندازه تصویر را برحسب اینچ مشخص میکند. گزینه layout="constrained" نیز به جلوگیری از همپوشانی عنوان، برچسبها و نمودارها کمک میکند. مستندات Matplotlib استفاده از Constrained Layout را برای مدیریت چیدمان پیچیده پیشنهاد میکنند.
دو روش رسم نمودار در Matplotlib
در Matplotlib دو سبک متداول وجود دارد.
روش Pyplot
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [10, 20, 15])
plt.title("Simple Chart")
plt.show()
این روش برای آزمایش سریع در Notebook مناسب است.
روش شیءگرا
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [10, 20, 15])
ax.set_title("Simple Chart")
plt.show()
روش شیءگرا برای پروژههای واقعی بهتر است؛ زیرا کنترل هر نمودار، محور، عنوان و عنصر را بهصورت مستقل در اختیار شما قرار میدهد.
انتخاب نمودار مناسب
انتخاب نمودار باید براساس نوع پرسش انجام شود.
| هدف | نمودار مناسب |
|---|---|
| نمایش تغییرات در زمان | نمودار خطی |
| مقایسه چند دسته | نمودار میلهای |
| بررسی رابطه دو متغیر | نمودار پراکندگی |
| مشاهده توزیع مقادیر | هیستوگرام |
| بررسی میانه و دادههای پرت | Box Plot |
| نمایش سهم اجزای محدود از کل | نمودار دایرهای |
| نمایش ماتریس یا شدت مقادیر | Heatmap |
| مقایسه چند سری در زمان | چند نمودار خطی یا Area Chart |
نمودار زیبا لزوماً نمودار مفیدی نیست. قبل از انتخاب ظاهر نمودار، مشخص کنید خواننده باید چه نتیجهای از آن بگیرد.
رسم نمودار خطی یا Line Plot
نمودار خطی برای نمایش روند در طول زمان مناسب است.
import matplotlib.pyplot as plt
days = [1, 2, 3, 4, 5, 6, 7]
visits = [850, 920, 880, 1100, 1250, 1190, 1420]
fig, ax = plt.subplots(figsize=(10, 5), layout="constrained")
ax.plot(
days,
visits,
color="#5B3DF5",
marker="o",
linewidth=2.5,
label="Website visits"
)
ax.set_title("Daily Website Visits")
ax.set_xlabel("Day")
ax.set_ylabel("Visits")
ax.set_xticks(days)
ax.grid(axis="y", linestyle="--", alpha=0.3)
ax.legend()
plt.show()
برای مقایسه دو سری داده:
organic = [500, 550, 530, 680, 790, 760, 910]
paid = [350, 370, 350, 420, 460, 430, 510]
fig, ax = plt.subplots(figsize=(10, 5), layout="constrained")
ax.plot(days, organic, marker="o", label="Organic")
ax.plot(days, paid, marker="s", label="Paid")
ax.set_title("Traffic Sources")
ax.set_xlabel("Day")
ax.set_ylabel("Visits")
ax.legend()
ax.grid(alpha=0.25)
plt.show()
اگر نمودار بیش از پنج یا شش خط داشته باشد، خوانایی آن کاهش پیدا میکند. در چنین حالتی بهتر است سریها را در چند نمودار جداگانه نمایش دهید.
رسم نمودار میلهای یا Bar Chart
نمودار میلهای برای مقایسه مقدار دستهها کاربرد دارد:
import matplotlib.pyplot as plt
categories = ["Mobile", "Laptop", "Tablet", "Accessories"]
revenue = [480, 720, 260, 390]
fig, ax = plt.subplots(figsize=(9, 5), layout="constrained")
bars = ax.bar(
categories,
revenue,
color=["#6C4DF6", "#8B73FF", "#A99AFF", "#C8BEFF"]
)
ax.set_title("Revenue by Category")
ax.set_xlabel("Category")
ax.set_ylabel("Revenue")
ax.bar_label(bars, padding=4)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.show()
نمودار میلهای افقی
برای نامهای طولانی، نمودار افقی معمولاً خواناتر است:
products = [
"AI API Subscription",
"Data Analysis Service",
"Automation Platform",
"Cloud Infrastructure"
]
values = [850, 610, 470, 730]
fig, ax = plt.subplots(figsize=(10, 5), layout="constrained")
bars = ax.barh(products, values, color="#6C4DF6")
ax.bar_label(bars, padding=5)
ax.set_title("Revenue by Product")
ax.set_xlabel("Revenue")
ax.invert_yaxis()
plt.show()
رسم نمودار پراکندگی یا Scatter Plot
Scatter Plot برای بررسی رابطه میان دو متغیر عددی استفاده میشود.
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(42)
advertising_cost = rng.integers(10, 100, size=60)
sales = advertising_cost * 2.4 + rng.normal(0, 25, size=60)
fig, ax = plt.subplots(figsize=(9, 5), layout="constrained")
ax.scatter(
advertising_cost,
sales,
color="#6C4DF6",
alpha=0.75,
edgecolor="white",
s=70
)
ax.set_title("Advertising Cost vs Sales")
ax.set_xlabel("Advertising Cost")
ax.set_ylabel("Sales")
ax.grid(alpha=0.2)
plt.show()
از روی نمودار میتوان یک رابطه مثبت احتمالی بین هزینه تبلیغات و فروش مشاهده کرد؛ اما وجود همبستگی بهتنهایی رابطه علت و معلولی را ثابت نمیکند.
رسم هیستوگرام
هیستوگرام برای مشاهده توزیع یک متغیر عددی مناسب است.
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(42)
response_times = rng.normal(loc=320, scale=65, size=1000)
fig, ax = plt.subplots(figsize=(9, 5), layout="constrained")
ax.hist(
response_times,
bins=30,
color="#6C4DF6",
edgecolor="white",
alpha=0.85
)
ax.axvline(
response_times.mean(),
color="#EF476F",
linestyle="--",
linewidth=2,
label=f"Mean: {response_times.mean():.1f} ms"
)
ax.set_title("API Response Time Distribution")
ax.set_xlabel("Response Time (ms)")
ax.set_ylabel("Frequency")
ax.legend()
plt.show()
پارامتر bins تعداد بازههای هیستوگرام را مشخص میکند. تعداد بسیار کم باعث پنهان شدن جزئیات و تعداد بسیار زیاد باعث تولید نمودار شلوغ میشود.
رسم Box Plot و شناسایی دادههای پرت
Box Plot برای مقایسه توزیع چند گروه و مشاهده دادههای پرت مفید است:
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(10)
model_a = rng.normal(420, 55, 150)
model_b = rng.normal(360, 45, 150)
model_c = rng.normal(510, 70, 150)
fig, ax = plt.subplots(figsize=(9, 5), layout="constrained")
box = ax.boxplot(
[model_a, model_b, model_c],
tick_labels=["Model A", "Model B", "Model C"],
patch_artist=True
)
for patch, color in zip(
box["boxes"],
["#6C4DF6", "#00A6A6", "#FF9F1C"]
):
patch.set_facecolor(color)
patch.set_alpha(0.65)
ax.set_title("Model Latency Comparison")
ax.set_ylabel("Latency (ms)")
ax.grid(axis="y", alpha=0.2)
plt.show()
خط وسط هر جعبه معمولاً میانه را نشان میدهد. نقاط خارج از محدوده اصلی میتوانند داده پرت باشند، اما نباید بدون بررسی حذف شوند.
نمودار دایرهای؛ چه زمانی استفاده کنیم؟
Pie Chart فقط زمانی مناسب است که:
- تعداد دستهها کم باشد
- مجموع دستهها یک کل معنادار تشکیل دهد
- اختلاف سهمها واضح باشد
import matplotlib.pyplot as plt
labels = ["Organic", "Direct", "Referral", "Social"]
sizes = [45, 25, 18, 12]
fig, ax = plt.subplots(figsize=(7, 7), layout="constrained")
ax.pie(
sizes,
labels=labels,
autopct="%1.1f%%",
startangle=90,
colors=["#6C4DF6", "#00A6A6", "#FF9F1C", "#EF476F"]
)
ax.set_title("Traffic Share")
ax.axis("equal")
plt.show()
برای مقایسه دقیق مقادیر، نمودار میلهای معمولاً انتخاب بهتری است. انسان طول میلهها را دقیقتر از زاویه قطعات یک دایره مقایسه میکند.
رسم نمودار با دادههای Pandas
در پروژههای واقعی معمولاً داده را با Pandas میخوانیم و پس از پاکسازی با Matplotlib رسم میکنیم.
فرض کنید فایل sales.csv چنین ستونهایی دارد:
date,category,city,orders,revenue
2026-01-01,Mobile,Tehran,18,54000000
2026-01-02,Laptop,Shiraz,7,63000000
کد خواندن و رسم درآمد روزانه:
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
df = pd.read_csv("sales.csv")
df["date"] = pd.to_datetime(df["date"], errors="coerce")
df["revenue"] = pd.to_numeric(df["revenue"], errors="coerce")
df = df.dropna(subset=["date", "revenue"])
daily_revenue = (
df.groupby("date", as_index=False)["revenue"]
.sum()
.sort_values("date")
)
fig, ax = plt.subplots(figsize=(12, 5), layout="constrained")
ax.plot(
daily_revenue["date"],
daily_revenue["revenue"],
color="#6C4DF6",
linewidth=2.3
)
ax.set_title("Daily Revenue")
ax.set_xlabel("Date")
ax.set_ylabel("Revenue")
ax.yaxis.set_major_formatter(
FuncFormatter(lambda value, position: f"{value / 1_000_000:.0f}M")
)
ax.grid(axis="y", alpha=0.25)
plt.show()
پیش از رسم داده باید چند مورد را بررسی کنید:
print(df.info())
print(df.isna().sum())
print(df.describe())
print(df.duplicated().sum())
اگر اعداد یا تاریخها بهشکل رشته وارد Matplotlib شوند، نمودار ممکن است دستهبندی اشتباه، محور شلوغ یا ترتیب نادرست داشته باشد.
نمایش صحیح متن فارسی در Matplotlib
در بعضی محیطها، متن فارسی در نمودار بهصورت جدا از هم یا با ترتیب نادرست نمایش داده میشود. برای رفع این مشکل میتوان از arabic-reshaper و python-bidi استفاده کرد.
import arabic_reshaper
from bidi.algorithm import get_display
def fa(text):
reshaped = arabic_reshaper.reshape(str(text))
return get_display(reshaped)
اکنون میتوانید عنوان و برچسب فارسی بسازید:
import matplotlib.pyplot as plt
cities = ["تهران", "شیراز", "تبریز", "مشهد"]
sales = [820, 460, 390, 610]
fig, ax = plt.subplots(figsize=(9, 5), layout="constrained")
bars = ax.bar(
[fa(city) for city in cities],
sales,
color="#6C4DF6"
)
ax.set_title(fa("فروش به تفکیک شهر"), fontsize=16)
ax.set_xlabel(fa("شهر"))
ax.set_ylabel(fa("میزان فروش"))
ax.bar_label(bars, padding=4)
plt.show()
استفاده از فونت فارسی
داشتن جهت صحیح بهتنهایی کافی نیست. فونت انتخابی نیز باید حروف فارسی را پشتیبانی کند.
برای مثال، اگر فایل فونت Vazirmatn-Regular.ttf کنار برنامه قرار دارد:
from matplotlib.font_manager import FontProperties
font = FontProperties(fname="Vazirmatn-Regular.ttf")
ax.set_title(
fa("گزارش فروش ماهانه"),
fontproperties=font,
fontsize=16
)
برای اعمال فونت به برچسبهای محور:
for label in ax.get_xticklabels():
label.set_fontproperties(font)
استفاده از نام یک فونت بدون نصب بودن آن روی سیستم کافی نیست. برای خروجی قابل تکرار در سرور، بهتر است فایل فونت مجاز را همراه پروژه نگهداری و با مسیر مشخص بارگذاری کنید.
ساخت چند نمودار با Subplots
برای ساخت داشبورد میتوان چند Axes را در یک Figure قرار داد:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 13)
revenue = np.array([110, 125, 138, 145, 160, 172, 185, 181, 205, 218, 232, 250])
orders = np.array([45, 49, 55, 58, 63, 69, 75, 73, 81, 87, 92, 98])
fig, axes = plt.subplots(
2,
2,
figsize=(14, 8),
layout="constrained"
)
axes[0, 0].plot(x, revenue, marker="o", color="#6C4DF6")
axes[0, 0].set_title("Monthly Revenue")
axes[0, 1].bar(x, orders, color="#00A6A6")
axes[0, 1].set_title("Monthly Orders")
axes[1, 0].scatter(orders, revenue, color="#EF476F")
axes[1, 0].set_title("Orders vs Revenue")
axes[1, 1].hist(revenue, bins=8, color="#FF9F1C", edgecolor="white")
axes[1, 1].set_title("Revenue Distribution")
for ax in axes.flat:
ax.grid(alpha=0.2)
fig.suptitle("Business Performance Dashboard", fontsize=18)
plt.show()
ویژگی axes.flat اجازه میدهد بدون نوشتن حلقههای تودرتو، تنظیمات مشترک را روی تمام نمودارها اعمال کنید.
پروژه عملی: ساخت داشبورد فروش با Matplotlib
در این پروژه یک مجموعه داده نمونه تولید میکنیم و سپس چهار شاخص را نمایش میدهیم:
- روند درآمد روزانه
- درآمد براساس دسته محصول
- تعداد سفارش براساس شهر
- رابطه تعداد سفارش و درآمد
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
rng = np.random.default_rng(42)
dates = pd.date_range("2026-01-01", periods=120, freq="D")
categories = np.array(["Mobile", "Laptop", "Accessories", "Tablet"])
cities = np.array(["Tehran", "Shiraz", "Tabriz", "Mashhad"])
rows = 1200
df = pd.DataFrame({
"date": rng.choice(dates, size=rows),
"category": rng.choice(
categories,
size=rows,
p=[0.30, 0.25, 0.30, 0.15]
),
"city": rng.choice(cities, size=rows),
"orders": rng.integers(1, 20, size=rows),
"average_order_value": rng.integers(
1_500_000,
18_000_000,
size=rows
)
})
df["revenue"] = (
df["orders"] * df["average_order_value"]
)
daily = (
df.groupby("date", as_index=False)
.agg(
revenue=("revenue", "sum"),
orders=("orders", "sum")
)
.sort_values("date")
)
category_revenue = (
df.groupby("category")["revenue"]
.sum()
.sort_values(ascending=False)
)
city_orders = (
df.groupby("city")["orders"]
.sum()
.sort_values()
)
money_formatter = FuncFormatter(
lambda value, position: f"{value / 1_000_000_000:.1f}B"
)
fig, axes = plt.subplots(
2,
2,
figsize=(16, 9),
layout="constrained"
)
fig.suptitle(
"Sales Performance Dashboard",
fontsize=20,
fontweight="bold"
)
axes[0, 0].plot(
daily["date"],
daily["revenue"],
color="#6C4DF6",
linewidth=2
)
axes[0, 0].set_title("Daily Revenue")
axes[0, 0].set_ylabel("Revenue")
axes[0, 0].yaxis.set_major_formatter(money_formatter)
category_bars = axes[0, 1].bar(
category_revenue.index,
category_revenue.values,
color="#00A6A6"
)
axes[0, 1].set_title("Revenue by Category")
axes[0, 1].yaxis.set_major_formatter(money_formatter)
axes[0, 1].tick_params(axis="x", rotation=15)
city_bars = axes[1, 0].barh(
city_orders.index,
city_orders.values,
color="#FF9F1C"
)
axes[1, 0].set_title("Orders by City")
axes[1, 0].bar_label(city_bars, padding=5)
axes[1, 1].scatter(
daily["orders"],
daily["revenue"],
color="#EF476F",
alpha=0.7,
s=55
)
axes[1, 1].set_title("Orders vs Revenue")
axes[1, 1].set_xlabel("Orders")
axes[1, 1].set_ylabel("Revenue")
axes[1, 1].yaxis.set_major_formatter(money_formatter)
for ax in axes.flat:
ax.grid(axis="y", alpha=0.2)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
fig.savefig(
"sales_dashboard.png",
dpi=160,
bbox_inches="tight",
facecolor="white"
)
plt.show()
این کد یک فایل sales_dashboard.png نیز تولید میکند که میتوان آن را در گزارش، پنل مدیریت یا مقاله استفاده کرد.
افزودن عنوان، توضیح و Annotation
گاهی یک نقطه خاص در نمودار اهمیت بیشتری دارد. میتوان آن را با فلش و توضیح مشخص کرد:
import numpy as np
import matplotlib.pyplot as plt
months = np.arange(1, 13)
sales = np.array([110, 124, 121, 139, 155, 162, 180, 176, 205, 198, 230, 270])
max_index = sales.argmax()
fig, ax = plt.subplots(figsize=(10, 5), layout="constrained")
ax.plot(months, sales, marker="o", color="#6C4DF6")
ax.annotate(
"Highest sales",
xy=(months[max_index], sales[max_index]),
xytext=(months[max_index] - 3, sales[max_index] - 35),
arrowprops={
"arrowstyle": "->",
"color": "#EF476F"
},
color="#EF476F",
fontweight="bold"
)
ax.set_title("Monthly Sales")
ax.set_xlabel("Month")
ax.set_ylabel("Sales")
ax.set_xticks(months)
plt.show()
Annotation زمانی مفید است که خواننده باید مستقیماً به یک رویداد، قله، افت یا نقطه غیرعادی توجه کند.
شخصیسازی ظاهر نمودار
میتوانید از Styleهای آماده استفاده کنید:
import matplotlib.pyplot as plt
print(plt.style.available)
plt.style.use("ggplot")
برای مشاهده نتیجهای نزدیک به سبک پیشفرض حرفهای:
plt.style.use("seaborn-v0_8-whitegrid")
برای تنظیمات سراسری:
import matplotlib.pyplot as plt
plt.rcParams.update({
"figure.figsize": (10, 5),
"figure.dpi": 120,
"axes.titlesize": 15,
"axes.labelsize": 12,
"axes.spines.top": False,
"axes.spines.right": False,
"legend.frameon": False
})
این تنظیمات روی نمودارهای بعدی همان اجرای برنامه اعمال میشوند.
در پروژههای بزرگ بهتر است تنظیمات ظاهری را در یک فایل Style یا ماژول جداگانه نگهداری کنید تا تمام گزارشها ظاهر یکسان داشته باشند.
استفاده صحیح از رنگها
رنگ باید معنا داشته باشد، نه اینکه فقط نمودار را تزئین کند.
چند اصل کاربردی:
- برای داده مشابه از رنگ مشابه استفاده کنید
- برای وضعیت منفی از رنگ هشدار استفاده کنید
- تعداد رنگهای اصلی را محدود نگه دارید
- تنها به تفاوت قرمز و سبز تکیه نکنید
- در نمودار خطی علاوه بر رنگ از Marker یا Line Style نیز استفاده کنید
- پسزمینه را ساده نگه دارید
- مهمترین سری را با رنگ برجستهتر نشان دهید
مثال:
ax.plot(x, current_year, color="#6C4DF6", linewidth=3, label="2026")
ax.plot(x, previous_year, color="#AEB4C0", linewidth=2, label="2025")
در این حالت، داده سال جاری برجستهتر دیده میشود.
فرمتکردن اعداد محور
برای نمایش عددهای بزرگ:
from matplotlib.ticker import FuncFormatter
def format_million(value, position):
return f"{value / 1_000_000:.1f}M"
ax.yaxis.set_major_formatter(FuncFormatter(format_million))
برای درصد:
from matplotlib.ticker import PercentFormatter
ax.yaxis.set_major_formatter(PercentFormatter(xmax=1))
برای جداکننده هزارگان:
from matplotlib.ticker import StrMethodFormatter
ax.yaxis.set_major_formatter(
StrMethodFormatter("{x:,.0f}")
)
فرمتکردن مناسب محور باعث میشود خواننده بهجای تلاش برای شمارش صفرها، روی مفهوم داده تمرکز کند.
رسم تاریخ در Matplotlib
برای نمودار زمانی، ستون تاریخ باید واقعاً نوع DateTime داشته باشد:
df["date"] = pd.to_datetime(df["date"], errors="coerce")
سپس میتوان برچسب تاریخ را خواناتر کرد:
import matplotlib.dates as mdates
ax.xaxis.set_major_locator(
mdates.MonthLocator()
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter("%Y-%m")
)
fig.autofmt_xdate()
اگر داده ساعتی یا روزانه زیاد دارید، نمایش تمام برچسبها باعث شلوغی میشود. Locator مشخص میکند کدام تاریخها روی محور نوشته شوند.
ذخیره نمودار در PNG، SVG و PDF
برای ذخیره تصویر PNG:
fig.savefig(
"chart.png",
dpi=200,
bbox_inches="tight",
facecolor="white"
)
برای ذخیره SVG:
fig.savefig(
"chart.svg",
bbox_inches="tight"
)
برای ذخیره PDF:
fig.savefig(
"chart.pdf",
bbox_inches="tight"
)
انتخاب فرمت به کاربرد بستگی دارد:
| فرمت | کاربرد پیشنهادی |
|---|---|
| PNG | وبسایت، شبکه اجتماعی و گزارش تصویری |
| SVG | وب و طرحهای برداری مقیاسپذیر |
| مقاله، چاپ و گزارش رسمی | |
| JPG | تصویر فشرده، معمولاً نه برای نمودارهای متنی |
| TIFF | برخی کاربردهای چاپ و انتشارات تخصصی |
برای چاپ، DPI بالاتر مناسب است. برای وب، DPI بسیار زیاد فقط حجم فایل را افزایش میدهد.
تولید نمودار در سرور بدون رابط گرافیکی
در سرور، Docker یا محیط CI ممکن است رابط گرافیکی وجود نداشته باشد. در این شرایط از Backend غیرتعاملی Agg استفاده کنید.
این تنظیم باید پیش از واردکردن pyplot انجام شود:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
سپس نمودار را ذخیره کنید و نیازی به plt.show() ندارید:
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [10, 20, 15])
fig.savefig("output.png", dpi=150)
plt.close(fig)
فراخوانی plt.close(fig) در سرویسهای طولانیمدت اهمیت دارد؛ زیرا باز ماندن Figureهای متعدد میتواند مصرف حافظه را افزایش دهد.
ارائه نمودار با FastAPI
میتوان نمودار را بدون ذخیره دائمی روی دیسک، مستقیماً از یک API برگرداند.
نصب وابستگیها:
pip install fastapi uvicorn matplotlib
فایل main.py:
from io import BytesIO
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
@app.get("/chart")
def create_chart():
months = ["Jan", "Feb", "Mar", "Apr", "May"]
sales = [120, 150, 145, 180, 210]
fig, ax = plt.subplots(
figsize=(10, 5),
layout="constrained"
)
ax.plot(
months,
sales,
color="#6C4DF6",
marker="o",
linewidth=2.5
)
ax.set_title("Monthly Sales")
ax.set_xlabel("Month")
ax.set_ylabel("Sales")
ax.grid(axis="y", alpha=0.25)
buffer = BytesIO()
fig.savefig(
buffer,
format="png",
dpi=150,
facecolor="white"
)
plt.close(fig)
buffer.seek(0)
return StreamingResponse(
buffer,
media_type="image/png"
)
اجرای سرور:
uvicorn main:app --reload
سپس آدرس زیر را باز کنید:
http://127.0.0.1:8000/chart
این الگو برای تولید گزارش، نمودار اختصاصی کاربر و تصاویر قابل نمایش در داشبورد مناسب است.
استفاده از Matplotlib در پروژههای یادگیری ماشین
یکی از کاربردهای مهم Matplotlib نمایش نتیجه آموزش مدل است.
رسم Loss و Accuracy
import matplotlib.pyplot as plt
epochs = range(1, 11)
train_loss = [0.92, 0.71, 0.58, 0.47, 0.39, 0.33, 0.29, 0.25, 0.22, 0.20]
val_loss = [0.95, 0.76, 0.62, 0.52, 0.46, 0.43, 0.42, 0.44, 0.48, 0.53]
fig, ax = plt.subplots(figsize=(10, 5), layout="constrained")
ax.plot(epochs, train_loss, marker="o", label="Train Loss")
ax.plot(epochs, val_loss, marker="s", label="Validation Loss")
ax.set_title("Training and Validation Loss")
ax.set_xlabel("Epoch")
ax.set_ylabel("Loss")
ax.legend()
ax.grid(alpha=0.25)
plt.show()
در این مثال، کاهش Loss آموزش همراه با افزایش Validation Loss در Epochهای پایانی میتواند نشانهای از Overfitting باشد.
رسم ماتریس درهمریختگی
import numpy as np
import matplotlib.pyplot as plt
matrix = np.array([
[82, 6, 2],
[7, 74, 9],
[1, 8, 81]
])
labels = ["Class A", "Class B", "Class C"]
fig, ax = plt.subplots(figsize=(7, 6), layout="constrained")
image = ax.imshow(matrix, cmap="Purples")
ax.set_xticks(range(len(labels)), labels=labels)
ax.set_yticks(range(len(labels)), labels=labels)
ax.set_xlabel("Predicted")
ax.set_ylabel("Actual")
ax.set_title("Confusion Matrix")
for row in range(matrix.shape[0]):
for column in range(matrix.shape[1]):
ax.text(
column,
row,
matrix[row, column],
ha="center",
va="center",
color="black"
)
fig.colorbar(image, ax=ax)
plt.show()
ترکیب Matplotlib با هوش مصنوعی درواره
Matplotlib نمودار را براساس داده دقیق تولید میکند. هوش مصنوعی میتواند در مرحله بعد، خلاصه آماری را بررسی و برای گزارش توضیح متنی ایجاد کند.
الگوی مناسب این است:
- داده خام را با Pandas اعتبارسنجی کنید
- شاخصها را با کد محاسبه کنید
- نمودار را با Matplotlib بسازید
- فقط خلاصه محاسبهشده را به مدل بفرستید
- از مدل بخواهید نتیجه را توضیح دهد، نه اینکه عدد جدید بسازد
برای دسترسی به مدلهای مختلف میتوانید در درواره ثبتنام کرده و API Key دریافت کنید. فهرست مدلها و قیمت بهروز آنها نیز در صفحه مدلهای درواره در دسترس است.
نصب کتابخانه Requests
pip install requests
نگهداری امن API Key
در Linux یا macOS:
export DARVAREH_API_KEY="YOUR_DARVAREH_API_KEY"
در PowerShell:
$env:DARVAREH_API_KEY="YOUR_DARVAREH_API_KEY"
کلید واقعی را در کد، مخزن Git یا فایل عمومی قرار ندهید.
ارسال خلاصه داده به API درواره
import json
import os
import pandas as pd
import requests
df = pd.read_csv("sales.csv")
df["revenue"] = pd.to_numeric(
df["revenue"],
errors="coerce"
)
df = df.dropna(subset=["revenue"])
summary = {
"total_revenue": float(df["revenue"].sum()),
"average_revenue": float(df["revenue"].mean()),
"median_revenue": float(df["revenue"].median()),
"minimum_revenue": float(df["revenue"].min()),
"maximum_revenue": float(df["revenue"].max()),
"row_count": int(len(df))
}
response = requests.post(
"https://api.darvareh.ir/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['DARVAREH_API_KEY']}",
"Content-Type": "application/json"
},
json={
"model": "YOUR_MODEL_ID",
"messages": [
{
"role": "system",
"content": (
"You are a data analysis assistant. "
"Use only the supplied numbers. "
"Do not invent missing facts."
)
},
{
"role": "user",
"content": (
"این خلاصه آماری فروش را به فارسی تحلیل کن. "
"سه نکته مهم و دو پیشنهاد برای بررسی بیشتر بده. "
"از ساختن عدد جدید خودداری کن.\n\n"
+ json.dumps(summary, ensure_ascii=False)
)
}
],
"temperature": 0.2
},
timeout=60
)
response.raise_for_status()
result = response.json()
print(result["choices"][0]["message"]["content"])
چرا نباید کل داده را بدون کنترل ارسال کنیم؟
ارسال مستقیم تمام ردیفهای یک فایل بزرگ معمولاً مناسب نیست؛ زیرا:
- مصرف توکن افزایش پیدا میکند
- هزینه بیشتر میشود
- احتمال نادیده گرفتن بخشهایی از داده وجود دارد
- کنترل صحت محاسبات دشوارتر میشود
- ممکن است اطلاعات غیرضروری یا حساس ارسال شود
محاسبات قطعی مانند مجموع، میانگین، میانه و گروهبندی را با Pandas انجام دهید. سپس از مدل برای توضیح، پیشنهاد نمودار و تولید متن گزارش کمک بگیرید.
انتخاب نمودار با کمک هوش مصنوعی
میتوانید ساختار داده را بدون ارسال ردیفهای واقعی برای مدل توضیح دهید:
schema = {
"date": "تاریخ ثبت سفارش",
"city": "شهر مشتری",
"category": "دسته محصول",
"orders": "تعداد سفارش",
"revenue": "درآمد روزانه"
}
پرامپت پیشنهادی:
برای یک مجموعه داده با ستونهای تاریخ، شهر، دسته محصول، تعداد سفارش و درآمد، سه نمودار مناسب پیشنهاد بده.
برای هر نمودار مشخص کن:
1. محور افقی چه باشد
2. محور عمودی چه باشد
3. چه گروهبندی لازم است
4. نمودار چه پرسشی را پاسخ میدهد
5. چه خطای تفسیری ممکن است رخ دهد
فقط پیشنهاد تحلیلی بده و عددی اختراع نکن.
پس از دریافت پیشنهاد، محاسبات و رسم واقعی را در کد انجام دهید.
ساخت تابع قابل استفاده مجدد برای نمودار
در پروژههای بزرگ بهتر است منطق رسم را داخل تابع قرار دهید:
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd
def create_daily_revenue_chart(
df: pd.DataFrame,
output_path: str
) -> Path:
required_columns = {"date", "revenue"}
missing = required_columns - set(df.columns)
if missing:
raise ValueError(
f"Missing columns: {sorted(missing)}"
)
clean_df = df.copy()
clean_df["date"] = pd.to_datetime(
clean_df["date"],
errors="coerce"
)
clean_df["revenue"] = pd.to_numeric(
clean_df["revenue"],
errors="coerce"
)
clean_df = clean_df.dropna(
subset=["date", "revenue"]
)
if clean_df.empty:
raise ValueError("No valid data to plot")
daily = (
clean_df.groupby("date", as_index=False)["revenue"]
.sum()
.sort_values("date")
)
fig, ax = plt.subplots(
figsize=(12, 5),
layout="constrained"
)
ax.plot(
daily["date"],
daily["revenue"],
color="#6C4DF6",
linewidth=2.5
)
ax.set_title("Daily Revenue")
ax.set_xlabel("Date")
ax.set_ylabel("Revenue")
ax.grid(axis="y", alpha=0.25)
path = Path(output_path)
path.parent.mkdir(
parents=True,
exist_ok=True
)
fig.savefig(
path,
dpi=160,
bbox_inches="tight",
facecolor="white"
)
plt.close(fig)
return path
استفاده از تابع:
df = pd.read_csv("sales.csv")
chart_path = create_daily_revenue_chart(
df,
"reports/daily_revenue.png"
)
print(chart_path)
این ساختار اعتبارسنجی، پاکسازی، رسم و ذخیره نمودار را قابل آزمایش و استفاده مجدد میکند.
بهینهسازی Matplotlib برای دادههای بزرگ
رسم میلیونها نقطه معمولاً ارزش تحلیلی ندارد و میتواند زمان و حافظه زیادی مصرف کند.
راهکارهای مناسب:
تجمیع داده
بهجای رسم تمام تراکنشها، داده را روزانه یا ساعتی تجمیع کنید:
daily = (
df.set_index("date")
.resample("D")["revenue"]
.sum()
)
نمونهبرداری
sample = df.sample(
n=min(20_000, len(df)),
random_state=42
)
حذف Markerهای غیرضروری
ax.plot(x, y, linewidth=1)
نمایش Marker برای صدها هزار نقطه باعث کاهش سرعت میشود.
Rasterize کردن لایه سنگین
ax.scatter(
x,
y,
s=3,
alpha=0.3,
rasterized=True
)
این گزینه هنگام تولید PDF یا SVG میتواند لایه سنگین نقاط را بهصورت Raster ذخیره کند و حجم خروجی را کاهش دهد.
بستن Figure
plt.close(fig)
در پردازش دستهای صدها نمودار، فراموش کردن این دستور میتواند مصرف حافظه را بالا ببرد.
خطاهای رایج Matplotlib و راهحل آنها
خطای ModuleNotFoundError
ModuleNotFoundError: No module named 'matplotlib'
راهحل:
python -m pip install matplotlib
استفاده از python -m pip کمک میکند بسته روی همان مفسر پایتونی نصب شود که برنامه را اجرا میکند.
باز نشدن پنجره نمودار
در اسکریپت محلی مطمئن شوید این دستور وجود دارد:
plt.show()
در سرور یا Docker بهجای نمایش، نمودار را با savefig ذخیره کنید.
ذخیره شدن تصویر خالی
این ترتیب ممکن است در بعضی شرایط خروجی نامناسب ایجاد کند:
plt.show()
fig.savefig("chart.png")
بهتر است ابتدا ذخیره و سپس نمایش دهید:
fig.savefig("chart.png")
plt.show()
روی هم افتادن عنوانها و برچسبها
از Constrained Layout استفاده کنید:
fig, ax = plt.subplots(
layout="constrained"
)
برای بیشتر پروژههای جدید، این روش از tight_layout انعطافپذیرتر است.
جدا نمایش داده شدن حروف فارسی
بستههای زیر را نصب کنید:
pip install arabic-reshaper python-bidi
سپس متن را با تابع fa تبدیل و از فونت دارای پشتیبانی فارسی استفاده کنید.
شلوغ شدن محور تاریخ
تعداد Tickها را محدود کنید یا از MonthLocator، WeekdayLocator و Formatter مناسب استفاده کنید.
نمایش اشتباه ترتیب اعداد
احتمال دارد ستون عددی از CSV بهشکل رشته خوانده شده باشد:
df["value"] = pd.to_numeric(
df["value"],
errors="coerce"
)
هشدار باز بودن Figureهای زیاد
پس از ذخیره هر تصویر:
plt.close(fig)
ناخوانا بودن Legend
اگر تعداد سریها زیاد است، نمودار را به چند بخش تقسیم کنید. جابهجایی Legend مشکل بنیادی تراکم اطلاعات را برطرف نمیکند.
اشتباهات رایج در طراحی نمودار
کوتاه کردن محور برای بزرگنمایی اختلاف
شروع نکردن محور میلهای از صفر میتواند تفاوتها را بیش از اندازه واقعی نشان دهد.
ax.set_ylim(bottom=0)
استفاده از نمودار سهبعدی بدون ضرورت
نمودار سهبعدی اغلب مقایسه مقادیر را دشوار میکند. تا زمانی که بُعد سوم واقعاً بخشی از داده نیست، نمودار دوبعدی انتخاب بهتری است.
استفاده بیش از حد از رنگ
اگر هر میله رنگ متفاوتی داشته باشد، خواننده تصور میکند رنگها معنای جداگانهای دارند.
حذف واحد اندازهگیری
برچسب Revenue کافی نیست. مشخص کنید مقدار ریال، تومان، دلار یا میلیون تومان است.
نمایش میانگین بدون توزیع
دو گروه ممکن است میانگین مشابه ولی توزیع بسیار متفاوت داشته باشند. در این موارد هیستوگرام یا Box Plot را نیز نمایش دهید.
رسم داده بدون پاکسازی
مقادیر گمشده، رکوردهای تکراری، تاریخهای نامعتبر و واحدهای ناسازگار باید پیش از رسم بررسی شوند.
Matplotlib یا ابزارهای دیگر؟
Matplotlib
مناسب برای:
- کنترل کامل روی جزئیات
- خروجی ثابت و باکیفیت
- گزارش و مقاله
- ساخت نمودار در سرور
- یادگیری ساختار اصلی مصورسازی پایتون
Seaborn
مناسب برای:
- نمودارهای آماری
- ظاهر آماده و زیبا
- کار سریع با DataFrame
- تحلیل توزیع و رابطه متغیرها
Plotly
مناسب برای:
- نمودار تعاملی
- Tooltip
- Zoom و Pan در مرورگر
- داشبورد تحت وب
Pandas Plot
مناسب برای:
- بررسی سریع داده
- نمودار ساده مستقیماً از DataFrame
برای گزارش تصویری ثابت و کنترل دقیق، Matplotlib انتخاب بسیار قدرتمندی است. برای داشبورد تعاملی تحت وب، Plotly ممکن است مناسبتر باشد.
چکلیست ساخت نمودار حرفهای
پیش از انتشار نمودار، این موارد را بررسی کنید:
- آیا نمودار یک پرسش مشخص را پاسخ میدهد؟
- آیا نوع نمودار با داده سازگار است؟
- آیا عنوان نتیجه یا موضوع را واضح بیان میکند؟
- آیا محور و واحد اندازهگیری مشخصاند؟
- آیا رنگها هدفمند و قابل تشخیص هستند؟
- آیا محور نمودار میلهای از صفر شروع شده است؟
- آیا داده گمشده و تکراری بررسی شده است؟
- آیا تاریخها مرتب شدهاند؟
- آیا اعداد بزرگ فرمت خوانا دارند؟
- آیا Legend واقعاً لازم است؟
- آیا نمودار در صفحه موبایل خوانا باقی میماند؟
- آیا منبع و بازه زمانی داده مشخص است؟
- آیا خروجی با DPI مناسب ذخیره شده است؟
- آیا متن فارسی بهدرستی نمایش داده میشود؟
- آیا Figure پس از تولید دستهای بسته میشود؟
پرسشهای متداول
Matplotlib چیست؟
Matplotlib کتابخانهای در پایتون برای رسم نمودار و مصورسازی داده است. با آن میتوان نمودار خطی، میلهای، پراکندگی، هیستوگرام، Box Plot، Heatmap و داشبوردهای چندنموداری ساخت.
آیا Matplotlib برای شروع مناسب است؟
بله. یادگیری مفاهیم Figure، Axes و Axis پایه مناسبی برای کار با سایر ابزارهای مصورسازی پایتون ایجاد میکند.
تفاوت Matplotlib و Pyplot چیست؟
Matplotlib نام کل کتابخانه است. matplotlib.pyplot ماژولی از آن است که توابعی برای ایجاد و مدیریت نمودار ارائه میکند.
آیا میتوان با Matplotlib متن فارسی نوشت؟
بله؛ اما در برخی محیطها برای اتصال صحیح حروف و جهت راستبهچپ باید از arabic-reshaper، python-bidi و یک فونت فارسی مناسب استفاده کنید.
آیا Matplotlib نمودار تعاملی میسازد؟
Matplotlib از تعامل در بعضی Backendها و محیطهای Notebook پشتیبانی میکند، اما برای داشبوردهای تعاملی مرورگر معمولاً Plotly یا ابزارهای مشابه مناسبتر هستند.
چگونه نمودار را باکیفیت ذخیره کنیم؟
از fig.savefig() همراه با dpi مناسب استفاده کنید:
fig.savefig(
"chart.png",
dpi=200,
bbox_inches="tight"
)
چگونه نمودار را در FastAPI برگردانیم؟
نمودار را داخل BytesIO ذخیره و سپس آن را با StreamingResponse و Media Type برابر image/png برگردانید.
آیا هوش مصنوعی میتواند نمودار بسازد؟
هوش مصنوعی میتواند در انتخاب نمودار، نوشتن کد و توضیح نتیجه کمک کند؛ اما محاسبات عددی و تولید نمودار نهایی بهتر است با ابزارهای قطعی مانند Pandas و Matplotlib انجام شود.
چگونه از درواره در تحلیل نمودار استفاده کنیم؟
پس از محاسبه شاخصهای آماری، خلاصه ساختاریافته را به API سازگار درواره بفرستید و از مدل بخواهید فقط براساس همان اعداد، گزارش یا توضیح تولید کند.
جمعبندی
Matplotlib یکی از پایهایترین و قدرتمندترین کتابخانههای مصورسازی داده در پایتون است. اگر Figure، Axes، انتخاب نوع نمودار، پاکسازی داده، فرمت محورها و ذخیره خروجی را بهدرستی یاد بگیرید، میتوانید از یک تحلیل ساده تا سامانه تولید گزارش خودکار را پیادهسازی کنید.
در یک معماری قابل اعتماد، وظایف بهتر است چنین تقسیم شوند:
- Pandas برای خواندن، پاکسازی و تجمیع داده
- NumPy برای محاسبات عددی
- Matplotlib برای تولید نمودار دقیق
- هوش مصنوعی برای توضیح، خلاصهسازی و پیشنهاد تحلیل
- درواره برای دسترسی یکپارچه API به مدلهای موردنیاز پروژه
برای شروع، در درواره ثبتنام کنید، API Key بگیرید و مدل مناسب را از صفحه مدلها و قیمتها انتخاب کنید. سپس میتوانید تحلیل متنی نمودارها و گزارشهای دادهمحور را به برنامه پایتون خود اضافه کنید.
مقالات مرتبط
- آموزش ساخت نمودار با هوش مصنوعی از روی داده
- آموزش تحلیل فایل CSV با هوش مصنوعی
- آموزش هوش مصنوعی برای Excel، فرمولنویسی و تحلیل داده
- آموزش تبدیل متن به جدول با هوش مصنوعی
- آموزش دریافت API Key هوش مصنوعی
- راهنمای اتصال API هوش مصنوعی به برنامه
برای مطالعه شرایط استفاده و محدودیتهای مسئولیت، صفحه «سلب مسئولیت» را مشاهده کنید.