পাঠ ২৫ · ৩০-এর মধ্যে · মডিউল ৪
Home / AI Courses / ডেটা সায়েন্স / Plotly দিয়ে interactive chart

Plotly দিয়ে interactive chart

Interactive charts with Plotly
৮ মিনিট পড়া মাঝারি · Intermediate Plotly কোডসহ

এই পাঠে যা শিখবেন

  • Plotly Express vs graph_objects — কখন কোনটা
  • Interactive feature — hover template, range slider, animation
  • Subplots দিয়ে multi-chart layout
  • HTML export ও web-এ embed করা

১ · Plotly কেন বিশেষ

Matplotlib আমাদের সবার পরিচিত — কিন্তু এর output static PNG। আজকের ব্যবহারকারী mouse hover করতে চায়, zoom করতে চায়, একটা region select করে দেখতে চায়। PlotlyPlotly২০১২-তে Montreal-এ শুরু হওয়া কোম্পানি ও open-source library — Python, R, JS-এ interactive visualization। Dash framework-এর core library। এই চাহিদা পূরণ করে — output একটি HTML+JS bundle, যা browser-এ চালালে complete interactivity।

Plotly-র দু'টি API আছে:

দু'টি API

১) Plotly Express (px): high-level — এক লাইন কোডে chart। pandas-friendly।
২) graph_objects (go): low-level — পূর্ণ control। যখন express-এ কাজ হয় না।

আজকের নিয়ম: ৮০% কাজে express যথেষ্ট। ২০% complex case-এ go। অনেক সময় express দিয়ে শুরু — তারপর fig.update_layout() দিয়ে fine-tune।

২ · প্রথম interactive chart

Python · plotly
import plotly.express as px
import pandas as pd

# Daraz-এর মাসিক বিক্রি
df = pd.DataFrame({
    'month': ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
    'revenue': [120, 135, 150, 145, 170, 195, 210, 225, 240, 260, 310, 380]
})

fig = px.line(df, x='month', y='revenue',
              title='মাসিক আয় — Daraz BD ২০২৫',
              markers=True)
fig.update_layout(yaxis_title='আয় (কোটি টাকা)',
                  template='plotly_white')
fig.show()

    
Output-এ একটি interactive line chart — mouse hover করলে exact value, scroll করে zoom, double-click-এ reset। সব built-in।

৩ · Hover template — তথ্য সমৃদ্ধ tooltip

Default hover-এ x ও y value দেখায়। কিন্তু আপনি custom message দিতে পারেন — ভাষা, format, additional column সবই।

Python · plotly
import plotly.express as px
import pandas as pd

df = pd.DataFrame({
    'product': ['Mobile','Fashion','Beauty','Home','Books'],
    'sales':   [320, 240, 180, 150, 110],
    'growth':  [12, -3, 25, 8, 5]   # % growth
})

fig = px.bar(df, x='product', y='sales', color='growth',
             color_continuous_scale='RdYlGn',
             title='পণ্য-শ্রেণিভিত্তিক বিক্রি')

fig.update_traces(
    hovertemplate='%{x}
' 'বিক্রি: %{y} কোটি
' 'বৃদ্ধি: %{marker.color}%' ) fig.show()

    
%{x}, %{y} Plotly placeholder। <extra></extra> দিয়ে default trace name বাদ। Color encoding — growth-এর উপর ভিত্তি করে red→yellow→green।

৪ · Animation — সময়ের সাথে data

Hans Rosling-এর বিখ্যাত GapMinder presentation-এ — দেশের income ও life expectancy ১৯৫০ → ২০২০ animate করে দেখানো। Plotly-তে এটা এক parameter:

Python · plotly
import plotly.express as px

# Plotly-র built-in gapminder dataset
df = px.data.gapminder()
df_asia = df[df['continent'] == 'Asia']

fig = px.scatter(df_asia,
    x='gdpPercap', y='lifeExp',
    animation_frame='year',
    animation_group='country',
    size='pop', color='country',
    hover_name='country',
    log_x=True, size_max=55,
    range_x=[100, 100000], range_y=[25, 90],
    title='এশিয়া — GDP ও life expectancy ১৯৫২-২০০৭')
fig.show()

    
Play button-এ চাপলে animation শুরু — slider-এ manual control। বাংলাদেশ (১৯৫২: ৩৭ বছর → ২০০৭: ৬৪ বছর) bubble উপরে উঠে যায়।

৫ · graph_objects — যখন express যথেষ্ট না

Express-এ চলে না এমন ক্ষেত্রে — যেমন একই plot-এ দু'টি ভিন্ন chart-type, custom legend group, secondary y-axis — go কাজে আসে।

Python · plotly
import plotly.graph_objects as go

months = ['Jan','Feb','Mar','Apr','May','Jun']
revenue = [120, 135, 150, 145, 170, 195]
margin  = [22, 25, 28, 26, 30, 33]   # %

fig = go.Figure()

# Bar — revenue
fig.add_trace(go.Bar(
    x=months, y=revenue, name='Revenue (Cr.)',
    marker_color='#2563eb', yaxis='y'
))

# Line — margin %
fig.add_trace(go.Scatter(
    x=months, y=margin, name='Margin %',
    mode='lines+markers', line=dict(color='#dc2626', width=3),
    yaxis='y2'
))

fig.update_layout(
    title='Revenue ও Margin — Q1+Q2',
    yaxis=dict(title='Revenue (কোটি)', side='left'),
    yaxis2=dict(title='Margin %', side='right', overlaying='y'),
    template='plotly_white',
    legend=dict(x=0.01, y=0.99)
)
fig.show()

    
Dual-axis — সাবধানে ব্যবহার করুন (পাঠ ২৪)। কিন্তু "revenue + margin %" এর মতো true relationship-এ গ্রহণযোগ্য।
Plotly architecture DataFrame → Figure → HTML pandas DataFrame df = pd.read_csv(...) Plotly Express px.bar, px.line, px.scatter graph_objects go.Figure() + add_trace Figure object fig.update_layout(...) fig.show() notebook display to_html() embed in webpage interactivity: hover · zoom · pan · select · animate Output = HTML + JS bundle (~3 MB)
Plotly-র workflow — DataFrame থেকে interactive HTML।

৬ · Subplots — dashboard-এর ভিত্তি

একটি page-এ একাধিক related chart — KPI dashboard-এর core। Plotly-র make_subplots এই কাজ করে।

Python · plotly
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 2x2 grid
fig = make_subplots(
    rows=2, cols=2,
    subplot_titles=('Revenue', 'Orders', 'AOV', 'Customers'),
    vertical_spacing=0.15
)

months = ['Jan','Feb','Mar','Apr','May','Jun']
fig.add_trace(go.Scatter(x=months, y=[120,135,150,145,170,195],
                         mode='lines+markers'), row=1, col=1)
fig.add_trace(go.Bar(x=months, y=[8500,9200,10100,9800,11500,13000]),
              row=1, col=2)
fig.add_trace(go.Scatter(x=months, y=[1410,1467,1485,1479,1478,1500],
                         mode='lines+markers'), row=2, col=1)
fig.add_trace(go.Bar(x=months, y=[450,480,520,510,560,620]),
              row=2, col=2)

fig.update_layout(height=600, showlegend=False,
                  title_text='Daraz BD — H1 KPI Dashboard',
                  template='plotly_white')
fig.show()

    

৭ · HTML export — যেকোনো website-এ embed

Plotly chart-এর সবচেয়ে বড় superpower — fig.write_html('chart.html')। একটি self-contained HTML file পাবেন, যা যেকোনো website, email, বা WhatsApp share-এ চলে। কোনো server লাগে না।

fig.write_html('dashboard.html', include_plotlyjs='cdn')
# include_plotlyjs='cdn' — file ছোট রাখে (~10 KB),
# Plotly JS CDN থেকে load হবে
Bangladesh-এ অনেক business-এর internal dashboard server নেই — analyst Excel email করেন। Plotly HTML email করলে boss browser-এ open করে interactive view পান। Big upgrade।

৮ · Range slider — time-series-এ অপরিহার্য

Python · plotly
import plotly.graph_objects as go
import pandas as pd
import numpy as np

dates = pd.date_range('2024-01-01', periods=365, freq='D')
sales = 1000 + np.cumsum(np.random.randn(365)*30) + np.linspace(0, 500, 365)

fig = go.Figure()
fig.add_trace(go.Scatter(x=dates, y=sales, mode='lines',
                         line=dict(color='#2563eb', width=2)))

fig.update_layout(
    title='দৈনিক বিক্রি ২০২৪',
    xaxis=dict(
        rangeslider=dict(visible=True),
        rangeselector=dict(buttons=[
            dict(count=7, label='1w', step='day', stepmode='backward'),
            dict(count=1, label='1m', step='month', stepmode='backward'),
            dict(count=3, label='3m', step='month', stepmode='backward'),
            dict(step='all', label='All')
        ])
    ),
    template='plotly_white'
)
fig.show()

    

৯ · Plotly বনাম matplotlib — কখন কোনটা

  • Static figure (paper, print, slide): matplotlib।
  • Interactive web-dashboard: Plotly।
  • Quick exploration in notebook: উভয়ই — preference।
  • Publication-quality: matplotlib (PDF vector output ভাল)।
  • Streamlit/Dash app: Plotly (built-in integration)।
Plotly chart বড় dataset-এ slow। ১ লক্ষের বেশি point থাকলে — datashader বা WebGL trace (scattergl) ব্যবহার করুন।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ Plotly-র interactive chart-এর কী কী trade-off আছে static-এর তুলনায়? কখন interactive হারাম?

Interactivity "more is more" না। নিচের trade-off গুলো গুরুত্বপূর্ণ।

(১) File size:

  • Plotly HTML বড় — Plotly JS bundle ~3 MB। CDN ব্যবহার না করলে প্রতিটি chart ~3 MB।
  • matplotlib PNG — সাধারণত ৫০-২০০ KB।
  • Email বা slow internet (Bangladesh গ্রাম) — Plotly slow।

(২) Performance:

  • ১০ লক্ষ point matplotlib রেন্ডার করে কয়েক সেকেন্ডে।
  • Plotly browser-এ — প্রায়ই ক্র্যাশ, বা ১ মিনিট+।
  • সমাধান: scattergl, datashader, downsample।

(৩) Print/PDF quality:

  • Plotly screen-first — print-এ pixelated বা broken।
  • matplotlib vector PDF — অসাধারণ print quality।
  • Academic paper-এ matplotlib অপরিহার্য।

(৪) Cognitive load:

  • Static chart পাঠকের চোখ direct গল্পে নিয়ে যায়।
  • Interactive — পাঠক explore করেন, কিন্তু গল্প হারিয়ে যেতে পারে।
  • Newspaper, infographic — static প্রায়ই better storytelling।

(৫) Maintenance:

  • Plotly upgrade করলে syntax কখনো ভাঙে।
  • matplotlib অনেক স্থিতিশীল API।
  • Long-term archival — matplotlib safer।

Interactive কখন harmful:

  • Single-shot insight delivery — "শুধু এই ১টি tikely message"।
  • Print medium।
  • Slow-internet audience।
  • Accessibility — screen reader-এ Plotly সমস্যা।

Hybrid approach:

  • Exploration — Plotly notebook-এ।
  • Final publication — matplotlib দিয়ে polished version।
  • Web dashboard — Plotly with downsampled data।

মূল উপলব্ধি: Tool বাছুন audience ও context-এর উপর — fad-এ না।

প্র ০২ Plotly Express একটাই function call — express নাকি graph_objects? Senior data engineer-এর কাছে এই সিদ্ধান্ত কীভাবে নেবেন?

Library design philosophy-র classic প্রশ্ন — convention vs configuration, ease vs power।

Express-এর শক্তি:

  • One-liner: px.bar(df, x='cat', y='val', color='group') — ৩০ সেকেন্ড।
  • pandas DataFrame integration — column name-ই enough।
  • Sensible defaults — প্রায়ই production-ready।
  • Faceting (small multiples) free: facet_col='region'।
  • Color, size, symbol mapping automatic।

Express-এর দুর্বলতা:

  • Multi-trace দিয়ে ভিন্ন chart-type একই plot-এ — কঠিন।
  • Custom legend grouping।
  • Dual y-axis — go লাগবে।
  • Animation customization limited।

graph_objects-এর শক্তি:

  • সম্পূর্ণ control — প্রতিটি trace, axis, annotation।
  • Multi-axis, secondary y, separate color scales।
  • Programmatic generation — loop-এ trace add।
  • Production dashboard-এ predictability।

graph_objects-এর দুর্বলতা:

  • Verbose — সাধারণ bar-এও ১০ লাইন।
  • Defaults নেই — সব নিজে set।
  • Documentation deeper exploration লাগে।

Practical strategy:

  1. Start with px: দ্রুত prototype।
  2. Convert when stuck: px.bar(...).update_traces() দিয়ে অনেক কিছু patch।
  3. Fall back to go: dual axis, complex layout, multi-trace integration।
  4. Reusable component: repeat-চলা chart-এর জন্য go-এ একটি function।

Example workflow:

  • Day 1: px.scatter(...) — exploration।
  • Day 5: stakeholder চাইলেন "এর সাথে moving average overlay"।
  • Day 5: fig.add_trace(go.Scatter(...)) — px figure-এ trace add।
  • Day 30: standardized dashboard component — pure go function।

Senior engineer-এর সাথে discussion:

  • "আমি express শুরু করি, ৮০% ক্ষেত্রে যথেষ্ট। বাকি ২০%-এ go-এ migrate করি।"
  • Reusable component-এ go ব্যবহার — testing ও type-hint সহজ।
  • "Single notebook-এ express, library code-এ go" — সাধারণ rule।

মূল উপলব্ধি: Tool ladder use করুন — top থেকে শুরু, প্রয়োজন হলে নিচে নামুন। কখনো শুরু থেকেই complexity choose করবেন না।

প্র ০৩ আপনার team Plotly dashboard build করেছে। কিন্তু load time ১৫ সেকেন্ড। কোথায় কোথায় optimize করবেন?

Performance optimization একটি real-world data engineering challenge। ১৫ সেকেন্ড — modern user-এর কাছে অগ্রহণযোগ্য (৩-সেকেন্ড rule)।

Diagnosis — কোথায় time যাচ্ছে?

  • Browser DevTools — Network ও Performance tab।
  • Server time vs client time — কোনটা slow?
  • Data size, JS execution, render time আলাদাভাবে measure।

Common causes:

(১) Data size — সবচেয়ে common।

  • ১০ লক্ষ row scatter — Plotly choke।
  • সমাধান: server-side aggregation। প্রতি দিন/ঘন্টা গড় — ১০৫০ row যথেষ্ট।
  • Sampling: random ১০,০০০ — pattern preserve হয়।
  • Datashader integration — ১০ লক্ষ point pre-render।

(২) Plotly JS bundle:

  • Default — ~3 MB। Slow connection-এ ৫ সেকেন্ড।
  • সমাধান: include_plotlyjs='cdn' — first load CDN cache।
  • Or: only-used-trace bundle (plotly.js-basic-dist)।

(৩) Multiple charts:

  • একটি page-এ ১০টি Plotly chart — multiplicative slow।
  • সমাধান: lazy load — viewport-এ এলে তবে render।
  • Tab/accordion — শুধু active tab render।

(৪) WebGL traces:

  • scattergl, scatter3d — GPU accelerated।
  • Regular scatter-এর তুলনায় ১০-১০০x faster বড় dataset-এ।

(৫) Update strategy:

  • Filter changed → পুরো recreate? — ভুল।
  • সঠিক: fig.update_traces() বা Dash callback partial update।

(৬) Server-side caching:

  • একই query বারবার? — Redis/lru_cache।
  • Streamlit-এ @st.cache_data।
  • Pre-aggregated table — query at-runtime না।

(৭) Image fallback:

  • "Snapshot" PNG — interactivity না দরকার এমন chart-এ।
  • Lighter than full Plotly।

Action plan:

  1. Profile: কোথায় time যাচ্ছে measure।
  2. Aggregate data: row count ১০K-এর নিচে।
  3. WebGL: scattergl ব্যবহার।
  4. CDN: Plotly JS।
  5. Cache: server-side query result।
  6. Lazy load: off-screen chart।

Target: ১৫সে → ২সে। Realistic ৭০-৮০% improvement।

মূল উপলব্ধি: Performance — premature optimization না, কিন্তু user-facing dashboard-এ critical। Profile first, then optimize।

প্র ০৪ Plotly chart-এ animation বানালেন। কিন্তু সিনিয়র বললেন "এটা gimmicky" — animation কখন justified, কখন না?

Animation একটি powerful tool — কিন্তু overuse করলে credibility-loss।

Animation justified যখন:

(১) সময়-ভিত্তিক transformation:

  • Hans Rosling-এর GapMinder — দেশের income/health ১৯৫০-২০২০।
  • চোখের সামনে evolve হতে দেখা — narrative power।
  • Static chart-এ ৫০ লাইন small multiples লাগত।

(২) State transition দেখানো:

  • Cluster algorithm step-by-step।
  • Optimization path (gradient descent)।
  • Educational demonstration।

(৩) Hierarchical drill-down:

  • সম্পূর্ণ → region → city — animated zoom।
  • "Continuity" preserve — বুঝতে সহজ।

Animation gimmicky যখন:

(১) Decorative spinning bar:

  • Bar চলতে চলতে final position-এ — কোনো information add করে না।
  • Reader's time waste।

(২) Print/PDF medium-এ:

  • Animation দেখাতে হলে static screenshot — animation-ই হারিয়ে যায়।
  • সরাসরি static design করুন।

(৩) Meaningful change নেই:

  • Year change-এ subtle difference — viewer ধরতে পারেন না।
  • Static side-by-side better।

(৪) Accessibility issue:

  • Vestibular disorder, autism — animation triggering।
  • Screen reader follow করতে পারে না।
  • prefers-reduced-motion CSS media query respect করুন।

Animation best practices:

  • Pause/play control — user বশে।
  • Speed reasonable (transition ৫০০-১০০০ms)।
  • Final state-এ থামা — না repeat loop।
  • Static fallback always available।
  • Caption/legend animation-এর সাথে synchronized।

Test:

  • "একই data static-এ যদি দিতাম, কি হারাতাম?" — কিছু না হারালে animation বাদ।
  • "Audience কি সত্যি pause/play ব্যবহার করবে?"

Bangladesh context:

  • Slow internet — animation buffer issue।
  • Mobile-first — small screen-এ animation hard।
  • Government/corporate — print-friendly preferred।

মূল উপলব্ধি: Animation = serious storytelling tool, gimmick না। প্রতিটি animation justify করতে শিখুন — "এটা না হলে গল্প বলা যায় না কেন?" উত্তর দিতে পারলে use করুন; না পারলে static।

অনুশীলন

  1. প্রথম interactive chart: ৫টি বাংলাদেশী city ও তাদের জনসংখ্যা — একটি sorted bar chart Plotly Express-এ।
    import plotly.express as px
    import pandas as pd
    
    df = pd.DataFrame({
        'city': ['Dhaka','Chattogram','Khulna','Rajshahi','Sylhet'],
        'pop':  [22, 5, 1.5, 0.9, 0.5]   # million
    }).sort_values('pop', ascending=True)
    
    fig = px.bar(df, x='pop', y='city', orientation='h',
                 title='বাংলাদেশের ৫ প্রধান শহর — জনসংখ্যা')
    fig.update_layout(template='plotly_white')
    fig.show()
  2. Hover customization: উপরের chart-এ hover-এ "Dhaka: ২২ মিলিয়ন (রাজধানী)" এর মতো custom message দিন।
    df['note'] = ['রাজধানী','বন্দরনগরী','দক্ষিণ-পশ্চিম',
                  'উত্তরাঞ্চল','উত্তর-পূর্ব']
    
    fig = px.bar(df, x='pop', y='city', orientation='h',
                 custom_data=['note'])
    fig.update_traces(
        hovertemplate='%{y}
    ' 'জনসংখ্যা: %{x} মিলিয়ন
    ' '%{customdata[0]}' ) fig.show()
  3. HTML export: উপরের figure-কে city.html-এ save করুন। File size কত? CDN দিয়ে কত কমে?
    # Default — Plotly JS embed: ~3.5 MB
    fig.write_html('city.html')
    
    # CDN — মাত্র ~10 KB!
    fig.write_html('city_cdn.html', include_plotlyjs='cdn')

    CDN-এ Plotly JS browser cache থেকে আসে — পরবর্তী chart-গুলোও দ্রুত load হয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

কোড রানার কাজ না করলে? ব্রাউজারে কাজ না করলে Google Colab ব্যবহার করুন।
পূর্ববর্তী পাঠ
পাঠ ২৪ · ভালো গ্রাফ-এর নীতি