آموزش Plotly؛ ساخت نمودار تعاملی و داشبورد با پایتون
در این آموزش جامع Plotly، ساخت نمودارهای تعاملی، داشبورد فروش، نمودار زمانی، Heatmap، خروجی HTML و PNG و ترکیب مصورسازی داده با هوش مصنوعی درواره را بهصورت عملی یاد میگیرید.
نمودارهای ثابت برای مقاله، گزارش و چاپ بسیار مناسباند؛ اما وقتی کاربر میخواهد روی داده Zoom کند، مقدار دقیق هر نقطه را ببیند، بعضی سریها را مخفی کند یا یک بازه زمانی خاص را بررسی کند، به نمودار تعاملی نیاز داریم.
Plotly یکی از محبوبترین کتابخانههای پایتون برای ساخت نمودارهای تعاملی است. نمودارهای ساختهشده با Plotly در مرورگر نمایش داده میشوند و میتوانند قابلیتهایی مانند Hover، Zoom، Pan، انتخاب نقاط، مخفیکردن سریها و ذخیره تصویر را در اختیار کاربر قرار دهند.
در این آموزش یاد میگیرید:
- Plotly چیست و چه تفاوتی با Matplotlib و Seaborn دارد
- چگونه Plotly را نصب و پیکربندی کنید
- تفاوت Plotly Express و Graph Objects چیست
- چگونه نمودار خطی، میلهای، پراکندگی و توزیع بسازید
- چگونه نمودار زمانی و Range Slider ایجاد کنید
- چگونه Subplot و داشبورد چندبخشی بسازید
- چگونه نمودار را در قالب HTML، PNG، SVG و PDF ذخیره کنید
- چگونه Plotly را در Streamlit و FastAPI استفاده کنید
- چگونه نمودارهای دارای داده زیاد را بهینه کنید
- چگونه خلاصه داده را برای تحلیل متنی به API درواره بفرستید
Plotly چیست؟
Plotly یک اکوسیستم مصورسازی داده است که کتابخانههایی برای زبانهای مختلف، از جمله پایتون و JavaScript، ارائه میکند. کتابخانه Plotly برای پایتون میتواند نمودارهای تعاملی مبتنی بر وب تولید کند.
نمودار Plotly فقط یک تصویر نیست. هر نمودار شامل داده، Traceها و تنظیمات Layout است و در مرورگر با استفاده از فناوریهای وب نمایش داده میشود.
قابلیتهای متداول Plotly عبارتاند از:
- نمایش مقدار دقیق نقاط با Hover
- Zoom روی محورهای نمودار
- حرکت یا Pan روی داده
- انتخاب بخشی از نقاط
- فعال و غیرفعالکردن سریها از طریق Legend
- ساخت Animation
- نمایش Range Slider
- ذخیره نمودار در فایل HTML
- خروجی PNG، SVG، WebP و PDF
- نمایش نمودار در Jupyter Notebook
- استفاده در Streamlit، Dash و برنامههای تحت وب
- ساخت نمودارهای دوبعدی و سهبعدی
تفاوت Plotly، Matplotlib و Seaborn
هر سه کتابخانه برای مصورسازی داده استفاده میشوند، اما کاربرد یکسانی ندارند.
| ویژگی | Plotly | Matplotlib | Seaborn |
|---|---|---|---|
| تعامل در مرورگر | بسیار خوب | محدود | محدود |
| Hover و Zoom | داخلی | وابسته به Backend | وابسته به Matplotlib |
| نمودار ثابت برای چاپ | خوب | بسیار خوب | بسیار خوب |
| تحلیل آماری | خوب | پایه | بسیار خوب |
| کنترل جزئیات | بسیار خوب | بسیار خوب | خوب |
| کار با Pandas | بسیار خوب | خوب | بسیار خوب |
| ساخت فایل HTML | داخلی | ندارد | ندارد |
| ساخت داشبورد تحت وب | بسیار مناسب | معمولاً مناسب نیست | معمولاً مناسب نیست |
| شروع سریع | آسان با Plotly Express | متوسط | آسان |
| خروجی برداری | SVG و PDF | SVG و PDF | از طریق Matplotlib |
اگر هدف شما مقاله چاپی یا تصویر کاملاً ثابت است، Matplotlib انتخاب قدرتمندی است. برای تحلیل آماری سریع، Seaborn بسیار مناسب است. برای نمودار تعاملی و داشبورد تحت وب، Plotly معمولاً انتخاب بهتری خواهد بود.
نصب Plotly
ابتدا محیط مجازی بسازید:
python -m venv .venv
فعالسازی در ویندوز:
.venv\Scripts\activate
فعالسازی در Linux یا macOS:
source .venv/bin/activate
نصب Plotly و کتابخانههای موردنیاز:
python -m pip install plotly pandas numpy
برای کار در Jupyter:
python -m pip install jupyter anywidget
برای خروجی ثابت PNG، SVG یا PDF:
python -m pip install --upgrade kaleido
برای بررسی نسخه:
python -c "import plotly; print(plotly.__version__)"
براساس راهنمای رسمی نصب Plotly، plotly را میتوان مستقیماً از PyPI نصب کرد و Plotly Express نیز بخشی از همین پکیج است.
اولین نمودار تعاملی با Plotly Express
import pandas as pd
import plotly.express as px
df = pd.DataFrame({
"month": [
"Jan", "Feb", "Mar",
"Apr", "May", "Jun"
],
"sales": [
120, 145, 138,
172, 190, 215
]
})
fig = px.line(
df,
x="month",
y="sales",
markers=True,
title="Monthly Sales"
)
fig.show()
پس از اجرای کد، نمودار در محیط Notebook یا مرورگر نمایش داده میشود. کاربر میتواند روی نقاط حرکت کند و مقدار دقیق هر ماه را ببیند.
ساختار Figure در Plotly
یک Figure در Plotly معمولاً دو بخش اصلی دارد:
Data
بخش data شامل یک یا چند Trace است. هر Trace یک سری داده یا لایه نمودار محسوب میشود؛ مانند یک خط، مجموعه نقاط یا سری میلهای.
Layout
بخش layout ظاهر و چیدمان نمودار را مشخص میکند:
- عنوان
- محور X و Y
- Legend
- رنگ پسزمینه
- اندازه نمودار
- Margin
- Annotation
- Hover Mode
برای مشاهده ساختار Figure:
print(fig)
یا تبدیل آن به Dictionary:
figure_dict = fig.to_dict()
print(figure_dict.keys())
خروجی شامل کلیدهای data و layout خواهد بود.
تفاوت Plotly Express و Graph Objects
Plotly دو رابط اصلی برای ساخت نمودار دارد.
Plotly Express
Plotly Express با نام px یک رابط سطح بالا برای ساخت سریع نمودار از DataFrame است.
import plotly.express as px
fig = px.scatter(
df,
x="advertising_cost",
y="sales",
color="channel",
size="conversion_rate"
)
مزایا:
- کد کمتر
- ارتباط مستقیم با Pandas
- ساخت خودکار Legend
- گروهبندی آسان با
color - Facet با
facet_colوfacet_row - مناسب تحلیل اکتشافی و داشبورد
Graph Objects
Graph Objects با نام go کنترل دقیقتری روی Traceها و Layout ارائه میدهد.
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=[1, 2, 3, 4],
y=[10, 18, 15, 24],
mode="lines+markers",
name="Sales"
)
)
fig.update_layout(
title="Sales Trend",
xaxis_title="Day",
yaxis_title="Sales"
)
fig.show()
Graph Objects برای موارد زیر مناسب است:
- ترکیب چند نوع نمودار
- ساخت Subplotهای پیچیده
- کنترل دقیق Hover
- اضافهکردن Shape و Annotation
- ساخت نمودارهایی که Plotly Express مستقیماً پوشش نمیدهد
در پروژههای واقعی میتوانید نمودار را با Plotly Express بسازید و سپس با متدهای update_layout و update_traces شخصیسازی کنید.
ساخت داده نمونه پروژه
در مثالهای بعدی از یک مجموعه داده فروش استفاده میکنیم:
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
rows = 1800
dates = pd.date_range(
"2026-01-01",
periods=180,
freq="D"
)
channels = np.array([
"Organic",
"Paid Search",
"Social",
"Referral"
])
categories = np.array([
"Mobile",
"Laptop",
"Tablet",
"Accessories"
])
cities = np.array([
"Tehran",
"Shiraz",
"Tabriz",
"Mashhad"
])
df = pd.DataFrame({
"date": rng.choice(dates, rows),
"channel": rng.choice(
channels,
rows,
p=[0.36, 0.28, 0.20, 0.16]
),
"category": rng.choice(
categories,
rows,
p=[0.30, 0.24, 0.16, 0.30]
),
"city": rng.choice(cities, rows),
"visits": rng.integers(
100,
1600,
rows
),
"conversion_rate": rng.uniform(
0.01,
0.10,
rows
),
"average_order_value": rng.integers(
1_500_000,
20_000_000,
rows
)
})
df["orders"] = np.maximum(
1,
np.round(
df["visits"]
* df["conversion_rate"]
)
).astype(int)
df["revenue"] = (
df["orders"]
* df["average_order_value"]
)
رسم نمودار خطی تعاملی
ابتدا درآمد روزانه را محاسبه میکنیم:
daily = (
df.groupby(
"date",
as_index=False
)
.agg(
revenue=("revenue", "sum"),
orders=("orders", "sum"),
visits=("visits", "sum")
)
.sort_values("date")
)
رسم نمودار:
import plotly.express as px
fig = px.line(
daily,
x="date",
y="revenue",
markers=True,
title="Daily Revenue",
labels={
"date": "Date",
"revenue": "Revenue"
}
)
fig.update_traces(
line={
"width": 3,
"color": "#6C4DF6"
},
marker={
"size": 6
}
)
fig.update_layout(
hovermode="x unified",
template="plotly_white"
)
fig.show()
گزینه hovermode="x unified" اطلاعات تمام سریهای مربوط به یک مقدار X را داخل یک Hover Box نمایش میدهد.
رسم چند سری زمانی
daily_channel = (
df.groupby(
["date", "channel"],
as_index=False
)["revenue"]
.sum()
.sort_values("date")
)
fig = px.line(
daily_channel,
x="date",
y="revenue",
color="channel",
title="Daily Revenue by Channel"
)
fig.update_layout(
hovermode="x unified",
template="plotly_white",
legend_title_text="Channel"
)
fig.show()
کاربر میتواند با کلیک روی نام هر کانال در Legend، آن سری را مخفی یا دوباره نمایش دهد.
افزودن Range Slider
برای داده زمانی میتوان Range Slider اضافه کرد:
fig.update_xaxes(
rangeslider_visible=True
)
همچنین میتوان دکمه انتخاب بازه زمانی ایجاد کرد:
fig.update_xaxes(
rangeselector={
"buttons": [
{
"count": 7,
"label": "7D",
"step": "day",
"stepmode": "backward"
},
{
"count": 1,
"label": "1M",
"step": "month",
"stepmode": "backward"
},
{
"count": 3,
"label": "3M",
"step": "month",
"stepmode": "backward"
},
{
"step": "all",
"label": "All"
}
]
},
rangeslider_visible=True
)
رسم Bar Chart
مجموع درآمد هر کانال:
channel_summary = (
df.groupby(
"channel",
as_index=False
)
.agg(
revenue=("revenue", "sum"),
orders=("orders", "sum")
)
.sort_values(
"revenue",
ascending=False
)
)
رسم نمودار:
fig = px.bar(
channel_summary,
x="channel",
y="revenue",
color="channel",
text_auto=".3s",
title="Total Revenue by Channel",
labels={
"channel": "Channel",
"revenue": "Revenue"
}
)
fig.update_layout(
showlegend=False,
template="plotly_white"
)
fig.update_traces(
textposition="outside",
hovertemplate=(
"<b>%{x}</b><br>"
"Revenue: %{y:,.0f}"
"<extra></extra>"
)
)
fig.show()
بخش <extra></extra> نام اضافی Trace را از Hover حذف میکند.
نمودار میلهای افقی
برای عنوانهای طولانی، Bar Chart افقی مناسبتر است:
category_summary = (
df.groupby(
"category",
as_index=False
)["revenue"]
.sum()
.sort_values(
"revenue",
ascending=True
)
)
fig = px.bar(
category_summary,
x="revenue",
y="category",
orientation="h",
color="revenue",
color_continuous_scale="Purples",
title="Revenue by Category"
)
fig.update_layout(
template="plotly_white",
coloraxis_showscale=False
)
fig.show()
رسم Grouped Bar Chart
برای مقایسه دستهها در کانالهای مختلف:
grouped = (
df.groupby(
["channel", "category"],
as_index=False
)["revenue"]
.sum()
)
fig = px.bar(
grouped,
x="channel",
y="revenue",
color="category",
barmode="group",
title="Revenue by Channel and Category"
)
fig.update_layout(
template="plotly_white"
)
fig.show()
برای نمودار رویهمقرارگرفته:
fig.update_layout(
barmode="stack"
)
نمودار Grouped برای مقایسه مستقیم دستهها مناسب است. Stacked Bar برای نمایش ترکیب کل مقدار کاربرد دارد.
رسم Scatter Plot
plot_sample = df.sample(
n=min(900, len(df)),
random_state=42
)
fig = px.scatter(
plot_sample,
x="visits",
y="revenue",
color="channel",
size="orders",
hover_data={
"category": True,
"city": True,
"conversion_rate": ":.2%",
"average_order_value": ":,.0f"
},
title="Visits vs Revenue"
)
fig.update_layout(
template="plotly_white"
)
fig.show()
در این نمودار:
- محور X تعداد بازدید را نشان میدهد
- محور Y درآمد را نمایش میدهد
- رنگ مشخصکننده کانال است
- اندازه نقطه تعداد سفارش را نمایش میدهد
- Hover اطلاعات تکمیلی ارائه میکند
استفاده همزمان از رنگ، اندازه و Symbol باید با احتیاط انجام شود؛ زیرا نمودار میتواند بیش از حد شلوغ شود.
افزودن Trendline
برای استفاده از Trendline باید statsmodels نصب باشد:
python -m pip install statsmodels
سپس:
fig = px.scatter(
plot_sample,
x="visits",
y="revenue",
color="channel",
trendline="ols",
title="Visits and Revenue Trend"
)
fig.show()
Trendline یک الگوی آماری را نمایش میدهد. وجود رابطه آماری یا همبستگی بهتنهایی اثباتکننده رابطه علت و معلولی نیست.
رسم Histogram
fig = px.histogram(
df,
x="average_order_value",
color="channel",
nbins=35,
marginal="box",
opacity=0.65,
barmode="overlay",
title="Order Value Distribution"
)
fig.update_layout(
template="plotly_white"
)
fig.show()
پارامتر marginal="box" یک Box Plot کوچک کنار توزیع قرار میدهد.
گزینههای دیگر:
marginal="rug"
marginal="violin"
marginal="histogram"
رسم Box Plot
fig = px.box(
df,
x="channel",
y="average_order_value",
color="channel",
points="outliers",
title="Order Value by Channel"
)
fig.update_layout(
template="plotly_white",
showlegend=False
)
fig.show()
برای نمایش تمام نقاط:
points="all"
در دادههای بزرگ، نمایش تمام نقاط باعث شلوغی و افزایش حجم نمودار میشود.
رسم Violin Plot
fig = px.violin(
plot_sample,
x="channel",
y="average_order_value",
color="channel",
box=True,
points=False,
title="Order Value Distribution"
)
fig.update_layout(
template="plotly_white",
showlegend=False
)
fig.show()
Violin Plot شکل تخمینی توزیع را نمایش میدهد. برای گروههایی با نمونه کم، تفسیر آن باید با احتیاط انجام شود.
رسم Heatmap همبستگی
ابتدا ماتریس همبستگی را محاسبه کنید:
numeric_columns = [
"visits",
"conversion_rate",
"orders",
"average_order_value",
"revenue"
]
correlation = (
df[numeric_columns]
.corr()
)
سپس Heatmap را بسازید:
fig = px.imshow(
correlation,
text_auto=".2f",
color_continuous_scale="RdBu_r",
zmin=-1,
zmax=1,
aspect="auto",
title="Correlation Matrix"
)
fig.update_layout(
template="plotly_white"
)
fig.show()
نکات مهم در تفسیر:
- مقدار نزدیک مثبت یک نشاندهنده رابطه خطی مثبت است
- مقدار نزدیک منفی یک رابطه خطی منفی را نشان میدهد
- مقدار نزدیک صفر فقط نبود رابطه خطی قوی را نشان میدهد
- همبستگی به معنای علت و معلول نیست
ساخت نمودار ترکیبی با Graph Objects
گاهی میخواهیم نمودار میلهای و خطی را با دو محور Y ترکیب کنیم.
from plotly.subplots import make_subplots
import plotly.graph_objects as go
monthly = (
df.set_index("date")
.resample("MS")
.agg(
revenue=("revenue", "sum"),
orders=("orders", "sum")
)
.reset_index()
)
ساخت نمودار:
fig = make_subplots(
specs=[
[
{
"secondary_y": True
}
]
]
)
fig.add_trace(
go.Bar(
x=monthly["date"],
y=monthly["revenue"],
name="Revenue",
marker_color="#B8A9FF"
),
secondary_y=False
)
fig.add_trace(
go.Scatter(
x=monthly["date"],
y=monthly["orders"],
name="Orders",
mode="lines+markers",
line={
"color": "#EF476F",
"width": 3
}
),
secondary_y=True
)
fig.update_layout(
title="Monthly Revenue and Orders",
template="plotly_white",
hovermode="x unified"
)
fig.update_yaxes(
title_text="Revenue",
secondary_y=False
)
fig.update_yaxes(
title_text="Orders",
secondary_y=True
)
fig.show()
محور دوم زمانی مناسب است که دو شاخص واحدهای متفاوت داشته باشند. استفاده بیدلیل از دو محور میتواند نمودار را گمراهکننده کند.
ساخت Subplot
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(
rows=2,
cols=2,
subplot_titles=[
"Daily Revenue",
"Revenue by Channel",
"Orders by Category",
"Visits vs Revenue"
],
specs=[
[
{"type": "xy"},
{"type": "xy"}
],
[
{"type": "xy"},
{"type": "xy"}
]
]
)
افزودن نمودار خطی:
fig.add_trace(
go.Scatter(
x=daily["date"],
y=daily["revenue"],
mode="lines",
name="Daily Revenue",
line={
"color": "#6C4DF6",
"width": 2.5
}
),
row=1,
col=1
)
افزودن نمودار کانالها:
fig.add_trace(
go.Bar(
x=channel_summary["channel"],
y=channel_summary["revenue"],
name="Channel Revenue",
marker_color="#00A6A6"
),
row=1,
col=2
)
مجموع سفارش هر دسته:
category_orders = (
df.groupby(
"category",
as_index=False
)["orders"]
.sum()
)
افزودن نمودار:
fig.add_trace(
go.Bar(
x=category_orders["category"],
y=category_orders["orders"],
name="Category Orders",
marker_color="#FF9F1C"
),
row=2,
col=1
)
افزودن Scatter Plot:
fig.add_trace(
go.Scattergl(
x=plot_sample["visits"],
y=plot_sample["revenue"],
mode="markers",
name="Visits vs Revenue",
marker={
"color": "#EF476F",
"size": 7,
"opacity": 0.55
}
),
row=2,
col=2
)
تنظیم نهایی:
fig.update_layout(
title="E-commerce Performance Dashboard",
height=850,
template="plotly_white",
showlegend=False
)
fig.update_xaxes(
title_text="Date",
row=1,
col=1
)
fig.update_yaxes(
title_text="Revenue",
row=1,
col=1
)
fig.update_xaxes(
title_text="Channel",
row=1,
col=2
)
fig.update_yaxes(
title_text="Revenue",
row=1,
col=2
)
fig.update_xaxes(
title_text="Category",
row=2,
col=1
)
fig.update_yaxes(
title_text="Orders",
row=2,
col=1
)
fig.update_xaxes(
title_text="Visits",
row=2,
col=2
)
fig.update_yaxes(
title_text="Revenue",
row=2,
col=2
)
fig.show()
شخصیسازی Hover
میتوان متن Hover را دقیقاً کنترل کرد:
fig.update_traces(
hovertemplate=(
"<b>Date:</b> %{x|%Y-%m-%d}<br>"
"<b>Revenue:</b> %{y:,.0f}<br>"
"<extra></extra>"
)
)
قالبهای متداول:
%{y:,.0f}
%{y:.2f}
%{y:.1%}
%{x|%Y-%m-%d}
استفاده از Hover مناسب باعث میشود نیازی به نوشتن تمام اعداد روی خود نمودار نباشد.
افزودن Annotation
max_row = daily.loc[
daily["revenue"].idxmax()
]
fig = px.line(
daily,
x="date",
y="revenue",
title="Daily Revenue"
)
fig.add_annotation(
x=max_row["date"],
y=max_row["revenue"],
text="Highest revenue",
showarrow=True,
arrowhead=2,
ax=-50,
ay=-55,
bgcolor="#FFF2B2"
)
fig.show()
Annotation برای مشخصکردن قله، افت، تغییر مهم یا یک رویداد خاص مناسب است.
افزودن خط هدف
target = daily["revenue"].mean()
fig.add_hline(
y=target,
line_dash="dash",
line_color="#EF476F",
annotation_text="Average"
)
برای مشخصکردن بازه:
fig.add_vrect(
x0="2026-03-01",
x1="2026-03-15",
fillcolor="#FFD166",
opacity=0.18,
line_width=0,
annotation_text="Campaign"
)
نمایش متن فارسی در Plotly
Plotly نمودار را در مرورگر رندر میکند. در نتیجه، پشتیبانی از متن فارسی معمولاً بهتر از بعضی موتورهای رسم ثابت است.
persian_df = pd.DataFrame({
"شهر": [
"تهران",
"شیراز",
"تبریز",
"مشهد"
],
"فروش": [
820,
470,
390,
610
]
})
fig = px.bar(
persian_df,
x="شهر",
y="فروش",
color="فروش",
color_continuous_scale="Purples",
title="فروش به تفکیک شهر"
)
fig.update_layout(
font={
"family": "Vazirmatn, Tahoma, Arial",
"size": 14
},
title={
"x": 0.95,
"xanchor": "right"
},
xaxis_title="شهر",
yaxis_title="میزان فروش",
template="plotly_white"
)
fig.show()
اگر نمودار در وبسایت نمایش داده میشود، باید فونت موردنظر در CSS صفحه نیز بارگذاری شده باشد. نوشتن نام فونت در Layout باعث نصب یا بارگذاری خودکار آن نمیشود.
تنظیم Template اختصاصی
import plotly.io as pio
darvareh_template = {
"layout": {
"font": {
"family": (
"Vazirmatn, Tahoma, Arial"
),
"color": "#1A1A2E"
},
"paper_bgcolor": "#FFFFFF",
"plot_bgcolor": "#FFFFFF",
"colorway": [
"#6C4DF6",
"#00A6A6",
"#EF476F",
"#FF9F1C",
"#118AB2"
],
"xaxis": {
"gridcolor": "#ECECF4",
"zerolinecolor": "#DADAE6"
},
"yaxis": {
"gridcolor": "#ECECF4",
"zerolinecolor": "#DADAE6"
}
}
}
pio.templates[
"darvareh"
] = darvareh_template
pio.templates.default = "darvareh"
پس از آن، نمودارهای جدید از این Template استفاده میکنند.
ذخیره نمودار تعاملی در HTML
یکی از قابلیتهای مهم Plotly ذخیره نمودار همراه با تعامل کامل در یک فایل HTML است.
fig.write_html(
"sales_dashboard.html"
)
فایل تولیدشده را میتوان با مرورگر باز کرد.
مطابق راهنمای رسمی خروجی HTML در Plotly، متد write_html میتواند Figure را به یک فایل HTML تعاملی تبدیل کند.
فایل مستقل برای استفاده آفلاین
fig.write_html(
"dashboard_offline.html",
include_plotlyjs=True,
full_html=True
)
این روش کد Plotly.js را داخل فایل قرار میدهد؛ بنابراین فایل بدون اینترنت نیز قابل استفاده است، اما حجم آن بیشتر خواهد بود.
فایل کوچکتر با CDN
fig.write_html(
"dashboard.html",
include_plotlyjs="cdn",
full_html=True
)
این فایل کوچکتر است، اما برای بارگذاری کتابخانه JavaScript به اینترنت نیاز دارد.
خروجی قطعه HTML
برای قراردادن نمودار داخل Template وب:
chart_html = fig.to_html(
full_html=False,
include_plotlyjs="cdn"
)
متغیر chart_html را میتوان داخل Template برنامه قرار داد.
خروجی PNG، SVG و PDF
برای خروجی تصویر ثابت از Kaleido استفاده میشود:
python -m pip install --upgrade kaleido
خروجی PNG:
fig.write_image(
"chart.png",
width=1600,
height=900,
scale=2
)
خروجی SVG:
fig.write_image(
"chart.svg"
)
خروجی PDF:
fig.write_image(
"chart.pdf"
)
خروجی WebP:
fig.write_image(
"chart.webp",
width=1600,
height=900
)
براساس مستندات رسمی خروجی ثابت Plotly، نسخههای جدید Kaleido برای رندر تصویر به Chrome یا Chromium سازگار روی سیستم نیاز دارند.
اگر Chrome پیدا نشد، پس از نصب Kaleido میتوانید از دستور ارائهشده توسط آن استفاده کنید:
kaleido_get_chrome
در سرور بهتر است وجود Chrome یا Chromium در Docker Image و مسیر اجرای برنامه از قبل بررسی شود.
خروجی چند نمودار
برای تعداد کمی نمودار:
fig1.write_image("chart-1.png")
fig2.write_image("chart-2.png")
برای تعداد زیاد Figure، نسخههای جدید Plotly امکان استفاده از write_images را فراهم میکنند:
import plotly.io as pio
pio.write_images(
[
fig1,
fig2
],
[
"chart-1.png",
"chart-2.png"
]
)
این روش برای خروجی دستهای میتواند کارآمدتر از اجرای جداگانه write_image باشد.
نمایش Plotly در Streamlit
نصب Streamlit:
python -m pip install streamlit
فایل app.py:
import pandas as pd
import plotly.express as px
import streamlit as st
st.set_page_config(
page_title="Sales Dashboard",
layout="wide"
)
st.title("Sales Dashboard")
df = pd.read_csv(
"sales.csv",
parse_dates=["date"]
)
selected_channels = st.multiselect(
"Select channels",
options=sorted(
df["channel"].dropna().unique()
),
default=sorted(
df["channel"].dropna().unique()
)
)
filtered_df = df[
df["channel"].isin(
selected_channels
)
]
daily = (
filtered_df.groupby(
["date", "channel"],
as_index=False
)["revenue"]
.sum()
)
fig = px.line(
daily,
x="date",
y="revenue",
color="channel",
title="Daily Revenue"
)
fig.update_layout(
hovermode="x unified",
template="plotly_white"
)
st.plotly_chart(
fig,
width="stretch"
)
اجرا:
streamlit run app.py
Streamlit فیلترهای انتخابشده را دریافت و نمودار Plotly را دوباره تولید میکند.
ارائه نمودار با FastAPI
در این مثال Figure را به JSON تبدیل میکنیم تا برنامه Frontend بتواند آن را دریافت کند.
نصب:
python -m pip install fastapi uvicorn plotly pandas
فایل main.py:
import json
import pandas as pd
import plotly.express as px
import plotly.utils
from fastapi import FastAPI
app = FastAPI()
@app.get("/chart")
def get_chart():
df = pd.DataFrame({
"month": [
"Jan",
"Feb",
"Mar",
"Apr",
"May"
],
"sales": [
120,
145,
138,
180,
215
]
})
fig = px.line(
df,
x="month",
y="sales",
markers=True,
title="Monthly Sales"
)
figure_json = json.loads(
json.dumps(
fig,
cls=plotly.utils.PlotlyJSONEncoder
)
)
return {
"figure": figure_json
}
اجرای API:
uvicorn main:app --reload
آدرس:
http://127.0.0.1:8000/chart
Frontend میتواند مقدار figure.data و figure.layout را به Plotly.js بدهد.
تولید HTML نمودار در FastAPI
from fastapi.responses import HTMLResponse
@app.get(
"/chart/view",
response_class=HTMLResponse
)
def view_chart():
fig = px.bar(
x=["A", "B", "C"],
y=[10, 18, 14],
labels={
"x": "Category",
"y": "Value"
}
)
chart = fig.to_html(
full_html=True,
include_plotlyjs="cdn"
)
return HTMLResponse(
content=chart
)
این روش برای نمایش سریع نمودار مناسب است. در برنامههای بزرگتر بهتر است نمودار داخل Template یا کامپوننت Frontend قرار گیرد.
بهینهسازی Plotly برای دادههای بزرگ
تعامل کامل با صدها هزار یا میلیونها نقطه میتواند مرورگر را کند کند.
نمونهبرداری
plot_df = df.sample(
n=min(20_000, len(df)),
random_state=42
)
تجمیع داده
daily = (
df.set_index("date")
.resample("D")["revenue"]
.sum()
.reset_index()
)
استفاده از WebGL
در Plotly Express:
fig = px.scatter(
plot_df,
x="visits",
y="revenue",
render_mode="webgl"
)
در Graph Objects:
import plotly.graph_objects as go
fig = go.Figure(
go.Scattergl(
x=plot_df["visits"],
y=plot_df["revenue"],
mode="markers",
marker={
"size": 4,
"opacity": 0.45
}
)
)
کاهش اطلاعات Hover
ارسال تعداد زیادی فیلد برای هر نقطه، حجم Figure را افزایش میدهد. فقط ستونهای موردنیاز را در hover_data قرار دهید.
جلوگیری از تکرار Plotly.js
اگر چند فایل HTML را در یک پوشه ذخیره میکنید، قراردادن جداگانه Plotly.js داخل هر فایل میتواند حجم کلی را زیاد کند. گزینههای cdn یا directory را متناسب با محیط استفاده بررسی کنید.
ارسال داده خلاصهشده به مرورگر
محاسبات سنگین را در Backend یا Pandas انجام دهید و فقط داده لازم برای نمودار را به مرورگر بفرستید.
اتصال Plotly به هوش مصنوعی درواره
Plotly مسئول نمایش داده است. هوش مصنوعی میتواند خلاصه آماری محاسبهشده را توضیح دهد یا برای ادامه تحلیل پیشنهاد ارائه کند.
معماری مناسب:
- خواندن و اعتبارسنجی داده با Pandas
- محاسبه شاخصهای دقیق
- ساخت نمودار تعاملی با Plotly
- ارسال خلاصه ساختاریافته به مدل
- نمایش گزارش مدل کنار نمودار
برای دسترسی API به مدلهای مختلف میتوانید در درواره ثبتنام کنید. فهرست مدلها و قیمت بهروز آنها در صفحه مدلهای درواره قرار دارد.
نگهداری API Key
در Linux یا macOS:
export DARVAREH_API_KEY="YOUR_DARVAREH_API_KEY"
در PowerShell:
$env:DARVAREH_API_KEY="YOUR_DARVAREH_API_KEY"
API Key را مستقیماً داخل کد یا مخزن Git قرار ندهید.
محاسبه خلاصه با Pandas
summary = {
"total_revenue": float(
df["revenue"].sum()
),
"total_orders": int(
df["orders"].sum()
),
"total_visits": int(
df["visits"].sum()
),
"average_conversion_rate": float(
df["conversion_rate"].mean()
),
"median_order_value": float(
df["average_order_value"].median()
),
"top_channel": str(
channel_summary.iloc[0][
"channel"
]
),
"top_channel_revenue": float(
channel_summary.iloc[0][
"revenue"
]
)
}
ارسال خلاصه به API درواره
import json
import os
import requests
response = requests.post(
"https://api.darvareh.ir/v1/chat/completions",
headers={
"Authorization": (
f"Bearer "
f"{os.environ['DARVAREH_API_KEY']}"
),
"Content-Type": "application/json"
},
json={
"model": "YOUR_MODEL_ID",
"messages": [
{
"role": "system",
"content": (
"تو یک دستیار تحلیل داده هستی. "
"فقط براساس اطلاعات ورودی پاسخ بده. "
"هیچ عدد یا علت جدیدی اختراع نکن. "
"همبستگی را علیت معرفی نکن."
)
},
{
"role": "user",
"content": (
"خلاصه زیر مربوط به عملکرد "
"فروشگاه آنلاین است. چهار یافته "
"مهم، سه پرسش برای بررسی بیشتر "
"و یک خلاصه مدیریتی کوتاه بنویس."
"\n\n"
+ json.dumps(
summary,
ensure_ascii=False
)
)
}
],
"temperature": 0.2
},
timeout=60
)
response.raise_for_status()
result = response.json()
analysis_text = (
result["choices"][0]
["message"]
["content"]
)
print(analysis_text)
نمایش گزارش هوش مصنوعی کنار نمودار در Streamlit
import streamlit as st
left_column, right_column = st.columns(
[2, 1]
)
with left_column:
st.plotly_chart(
fig,
width="stretch"
)
with right_column:
st.subheader("تحلیل هوش مصنوعی")
st.write(analysis_text)
این الگو یک داشبورد ترکیبی ایجاد میکند:
- سمت اصلی: نمودار تعاملی
- کنار نمودار: خلاصه و تفسیر متنی
محاسبات عددی را با Pandas انجام دهید و از مدل برای توضیح و پیشنهاد استفاده کنید.
تولید پیشنهاد نمودار با هوش مصنوعی
میتوانید Schema داده و سؤال کسبوکار را برای مدل ارسال کنید:
schema = {
"date": "تاریخ ثبت سفارش",
"channel": "کانال جذب کاربر",
"category": "دسته محصول",
"city": "شهر",
"visits": "تعداد بازدید",
"conversion_rate": "نرخ تبدیل",
"orders": "تعداد سفارش",
"revenue": "درآمد"
}
پرامپت پیشنهادی:
برای مجموعه دادهای با ستونهای ارائهشده، پنج نمودار تعاملی مناسب با Plotly پیشنهاد بده.
برای هر نمودار مشخص کن:
1. سؤال تحلیلی چیست
2. تابع مناسب Plotly Express چیست
3. محور X و Y چه باشند
4. آیا color یا facet لازم است
5. چه GroupBy یا Resample باید با Pandas انجام شود
6. چه خطای تفسیری ممکن است رخ دهد
هیچ عددی تولید نکن و فقط از ستونهای معرفیشده استفاده کن.
خروجی مدل باید بهعنوان پیشنهاد بررسی شود. کد نهایی، محاسبات و نمودار باید روی داده واقعی آزمایش شوند.
ساخت تابع قابل استفاده مجدد
from pathlib import Path
import pandas as pd
import plotly.express as px
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: "
f"{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 = px.line(
daily,
x="date",
y="revenue",
markers=True,
title="Daily Revenue"
)
fig.update_layout(
template="plotly_white",
hovermode="x unified"
)
path = Path(output_path)
path.parent.mkdir(
parents=True,
exist_ok=True
)
fig.write_html(
path,
include_plotlyjs=True,
full_html=True
)
return path
استفاده:
chart_path = (
create_daily_revenue_chart(
df=df,
output_path=(
"reports/"
"daily-revenue.html"
)
)
)
print(chart_path)
تست ساده تابع تولید نمودار
def test_create_daily_revenue_chart(
tmp_path
):
test_df = pd.DataFrame({
"date": [
"2026-01-01",
"2026-01-02"
],
"revenue": [
100,
150
]
})
output = (
tmp_path
/ "chart.html"
)
result = (
create_daily_revenue_chart(
test_df,
str(output)
)
)
assert result.exists()
assert result.stat().st_size > 0
تست کمک میکند مطمئن شوید تابع با داده معتبر، فایل HTML واقعی تولید میکند.
خطاهای رایج Plotly
خطای نصب نبودن Plotly
ModuleNotFoundError: No module named 'plotly'
راهحل:
python -m pip install plotly
باز نشدن نمودار
در اسکریپت معمولی:
fig.show()
اگر Renderer محیط بهدرستی کار نمیکند:
import plotly.io as pio
pio.renderers.default = "browser"
پیدا نشدن ستون
ValueError: Value of 'x' is not the name of a column
ستونها را بررسی کنید:
print(df.columns.tolist())
حذف فاصله ابتدا و انتهای نام ستون:
df.columns = (
df.columns
.str.strip()
)
مرتب نبودن تاریخ
df["date"] = pd.to_datetime(
df["date"],
errors="coerce"
)
df = df.sort_values("date")
حجم زیاد فایل HTML
علت احتمالی:
- قراردادن Plotly.js داخل هر فایل
- تعداد بسیار زیاد نقطه
- Hover Data حجیم
- چند Trace بزرگ
برای فایل آنلاین:
fig.write_html(
"chart.html",
include_plotlyjs="cdn"
)
برای داده، از تجمیع یا نمونهبرداری استفاده کنید.
خطای Kaleido یا Chrome
ابتدا بستهها را بهروز کنید:
python -m pip install --upgrade plotly kaleido
نسخههای جدید Kaleido به Chrome یا Chromium سازگار نیاز دارند. در صورت نبود Chrome:
kaleido_get_chrome
خروجی PNG با فونت متفاوت
موتور تولید تصویر باید به فونت دسترسی داشته باشد. فونت موردنظر را روی سرور یا داخل Docker Image نصب کنید.
کندشدن مرورگر
راهکارها:
- نمونهبرداری
- تجمیع داده
- استفاده از WebGL
- کاهش Traceها
- حذف ستونهای غیرضروری از Hover
- ارسال داده خلاصهشده به Frontend
اشتباهات رایج در طراحی نمودار تعاملی
قراردادن همه اطلاعات در Hover
Hover باید اطلاعات تکمیلی مهم را نمایش دهد، نه کل رکورد را.
استفاده زیاد از رنگ و اندازه
نمایش بیش از چهار یا پنج بُعد در یک نمودار باعث کاهش خوانایی میشود.
استفاده از دو محور Y بدون ضرورت
محور دوم میتواند رابطه ظاهری گمراهکننده ایجاد کند. واحد هر محور باید کاملاً مشخص باشد.
رسم میلیونها نقطه
تعامل به معنای نمایش تمام داده خام نیست. هدف نمودار کمک به تصمیمگیری است، نه انتقال کل دیتابیس به مرورگر.
اتکا به نمودار بدون پاکسازی داده
نوع داده نادرست، مقدار گمشده یا رکورد تکراری میتواند نمودار تعاملی زیبا اما اشتباه تولید کند.
استفاده از نمودار سهبعدی برای جذابیت
نمودار سهبعدی همیشه اطلاعات بیشتری ارائه نمیدهد و ممکن است مقایسه مقادیر را دشوار کند.
ارسال مستقیم داده حساس به مرورگر
دادهای که داخل Figure قرار میگیرد میتواند در سمت کاربر قابل مشاهده باشد. فقط اطلاعات لازم برای نمودار را ارسال کنید.
چکلیست ساخت نمودار حرفهای Plotly
- سؤال تحلیل پیش از ساخت نمودار مشخص شده است
- نوع داده ستونها صحیح است
- دادههای گمشده و تکراری بررسی شدهاند
- داده زمانی مرتب شده است
- تجمیع با Pandas انجام شده است
- محور و واحد اندازهگیری مشخصاند
- عنوان نمودار واضح است
- Hover فقط اطلاعات ضروری را نمایش میدهد
- تعداد Traceها کنترل شده است
- Legend قابل فهم است
- رنگها معنای مشخص دارند
- نمودار در صفحه کوچک بررسی شده است
- داده زیاد نمونهبرداری یا تجمیع شده است
- نسخه HTML آفلاین و آنلاین آگاهانه انتخاب شده است
- خروجی ثابت در محیط Deployment آزمایش شده است
- Chrome یا Chromium برای Kaleido آماده است
- اعداد توسط کد محاسبه میشوند
- تفسیر هوش مصنوعی فقط براساس خلاصه معتبر انجام میشود
پرسشهای متداول
Plotly چیست؟
Plotly یک کتابخانه مصورسازی داده است که امکان ساخت نمودارهای تعاملی با قابلیت Hover، Zoom، Pan و انتخاب داده را فراهم میکند.
Plotly رایگان است؟
کتابخانه متنباز Plotly برای پایتون را میتوان در پروژههای پایتون استفاده کرد. محصولات و سرویسهای تجاری مرتبط ممکن است شرایط جداگانه داشته باشند.
تفاوت Plotly Express و Graph Objects چیست؟
Plotly Express برای ساخت سریع نمودار از DataFrame مناسب است. Graph Objects کنترل دقیقتری روی Traceها، Layout، Subplot و نمودارهای ترکیبی ارائه میدهد.
آیا Plotly به اینترنت نیاز دارد؟
خود کتابخانه میتواند نمودار را محلی تولید کند. فایل HTML اگر با include_plotlyjs=True ساخته شود، میتواند مستقل و آفلاین باشد. اگر از CDN استفاده شود، برای بارگذاری Plotly.js به اینترنت نیاز دارد.
چگونه نمودار Plotly را در HTML ذخیره کنیم؟
fig.write_html(
"chart.html"
)
چگونه نمودار را به PNG تبدیل کنیم؟
Kaleido را نصب و سپس از write_image استفاده کنید:
fig.write_image(
"chart.png"
)
نسخههای جدید Kaleido به Chrome یا Chromium سازگار نیاز دارند.
آیا Plotly متن فارسی را نمایش میدهد؟
بله. چون نمودار در مرورگر رندر میشود، متن فارسی معمولاً بهخوبی نمایش داده میشود. برای ظاهر یکسان باید فونت فارسی در صفحه یا محیط خروجی در دسترس باشد.
آیا Plotly برای دادههای بزرگ مناسب است؟
برای داده متوسط مناسب است. برای تعداد بسیار زیاد نقاط باید از تجمیع، نمونهبرداری، WebGL و کاهش اطلاعات Hover استفاده کنید.
آیا میتوان Plotly را در Streamlit استفاده کرد؟
بله. متد st.plotly_chart نمودار تعاملی Plotly را در برنامه Streamlit نمایش میدهد.
چگونه Plotly را با FastAPI استفاده کنیم؟
میتوانید Figure را به JSON تبدیل و برای Frontend ارسال کنید یا خروجی HTML آن را با HTMLResponse برگردانید.
چگونه از هوش مصنوعی کنار Plotly استفاده کنیم؟
شاخصهای قطعی را با Pandas محاسبه کنید، نمودار را با Plotly بسازید و خلاصه آماری را برای تولید گزارش متنی به API درواره ارسال کنید.
جمعبندی
Plotly یکی از بهترین گزینهها برای ساخت نمودار تعاملی و داشبورد دادهمحور با پایتون است. Plotly Express شروع کار را ساده میکند و Graph Objects کنترل لازم برای نمودارهای پیچیده، ترکیبی و چندبخشی را در اختیار توسعهدهنده قرار میدهد.
یک جریان کاری قابل اعتماد میتواند چنین ساختاری داشته باشد:
- Pandas برای خواندن، پاکسازی و تجمیع داده
- NumPy برای محاسبات عددی
- Plotly برای نمودار تعاملی
- Streamlit یا Frontend برای رابط کاربری
- FastAPI برای ارائه داده و Figure
- هوش مصنوعی برای توضیح و خلاصهسازی
- درواره برای دسترسی API یکپارچه به مدلهای موردنیاز
برای شروع، در درواره ثبتنام کنید، API Key بگیرید و مدل مناسب پروژه را از صفحه مدلها و قیمتها انتخاب کنید.
مقالات مرتبط
- آموزش ساخت نمودار با هوش مصنوعی از روی داده
- آموزش تحلیل فایل CSV با هوش مصنوعی
- هوش مصنوعی برای Excel، فرمولنویسی و تحلیل داده
- آموزش تبدیل متن به جدول با هوش مصنوعی
- آموزش کامل نوشتن گزارش با هوش مصنوعی
- آموزش دریافت API Key هوش مصنوعی
برای مطالعه شرایط استفاده و محدودیتهای مسئولیت، صفحه «سلب مسئولیت» را مشاهده کنید.