subplots: bir rasmda bir nechta grafik
Sahna: bitta varaqda butun hisobot
Rahbar uchun to'rtta alohida rasm emas, bitta varaq kerak: yuqorida trend, pastda tarkib, yonida taqqoslash. Matplotlib da bu — bitta Figure ichida bir nechta Axes. Bu bob shunday "dashboard" yasashni va undagi eng xavfli xatoni — har xil shkalani — o'rgatadi.
import numpy as np import pandas as pd savdo = pd.read_csv(DATA / "dokon_savdo.csv", parse_dates=["sana"], date_format="%d.%m.%Y") savdo["tushum"] = savdo["miqdor"] * savdo["narx"] savdo["oy"] = savdo["sana"].dt.month oylik = savdo.pivot_table(index="oy", columns="filial_id", values="tushum", aggfunc="sum") / 1e6 oylik.round(1).tail(3)
| oy | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| 10 | 13.6 | 12.8 | 12 | 10.1 | 10.8 |
| 11 | 10.1 | 11.3 | 9.6 | 10.8 | 10.3 |
| 12 | 16.3 | 12 | 13.9 | 15.1 | 14.7 |
Panjara: subplots(qator, ustun)
fig, axs = plt.subplots(2, 2, figsize=(10, 6)) print(type(axs).__name__, axs.shape) for ax, filial in zip(axs.flat, [1, 2, 3, 4]): ax.plot(oylik.index, oylik[filial], marker="o") ax.set_title(f"{filial}-filial") fig.suptitle("Filiallar oylik tushumi, mln so'm") plt.show()
ndarray (2, 2)

plt.subplots(2, 2) — axs — 2×2 NumPy array (7-bob mashqi): axs[0, 1] — birinchi qator, ikkinchi ustun. axs.flat — panjarani bitta qatorga yoyadi (6-bobdagi ravel kabi), shuning uchun bitta sikl bilan hamma chizmani to'ldirish mumkin. fig.suptitle — butun varaqning sarlavhasi; ax.set_title — har chizmaniki.
Eng xavfli xato: har xil shkala
Yuqoridagi rasmga qarang: to'rt filial o'xshash ko'rinadi. Lekin har bir chizmaning y o'qi o'zicha tanlangan. Endi umumiy o'q bilan:
fig, (chap, ong) = plt.subplots(1, 2, figsize=(10, 3.2)) chap.bar(oylik.columns.astype(str), oylik.sum(), color="#b06000") chap.set(title="Har filial yillik tushumi", ylim=(oylik.sum().nlargest(4).min() * 0.95, oylik.sum().max() * 1.01)) ong.bar(oylik.columns.astype(str), oylik.sum(), color="#137333") ong.set(title="O'sha ma'lumot, o'q noldan", ylim=(0, oylik.sum().max() * 1.1)) for ax in (chap, ong): ax.set_xlabel("filial") plt.show() print((oylik.sum() / oylik.sum().max() * 100).round(0).to_dict())
{1: 100.0, 2: 96.0, 3: 91.0, 4: 92.0, 5: 26.0}

Chapda o'q noldan emas, katta to'rt filialning eng kichigidan sal pastdan boshlanadi — 1- va 3-filial orasidagi 9% lik farq ulkan ko'rinadi, 5-filial esa o'qdan pastda qolib, umuman ko'rinmaydi. O'ngda — haqiqiy nisbat: 1–4 filial deyarli teng, 5-filial (oktyabrda ochilgan) ancha past. Bir xil sonlar, butunlay boshqa hikoya.
Bir nechta chizmani solishtirganda — sharey=True:
fig, axs = plt.subplots(1, 4, figsize=(12, 2.8), sharey=True) for ax, filial in zip(axs, [1, 2, 3, 4]): ax.bar(oylik.index, oylik[filial], color="#1a73e8") ax.set_title(f"{filial}-filial") axs[0].set_ylabel("mln so'm") plt.show()

sharey=True — hamma chizma bitta y o'qini bo'lishadi: endi balandlikni chizmadan chizmaga ko'z bilan solishtirish mumkin. Faqat chap chizmada son belgilari qoladi — takror yo'q. sharex=True — x o'qi uchun xuddi shunday (vaqt bo'yicha ustma-ust chizmalarda).
Har xil o'lchamli chizmalar: subplot_mosaic
Dashboard da chizmalar teng bo'lishi shart emas: trend — keng, qolganlari — kichik.
fig, axd = plt.subplot_mosaic([["trend", "trend", "trend"], ["tolov", "kun", "soat"]], figsize=(12, 6), layout="constrained") kunlik = savdo.set_index("sana")["tushum"].resample("D").sum() / 1e6 axd["trend"].plot(kunlik.index, kunlik.rolling(7).mean(), color="#1a73e8") axd["trend"].set_title("Kunlik tushum, 7 kunlik o'rtacha, mln so'm") tolov = savdo.groupby("tolov")["tushum"].sum().sort_values() / 1e6 axd["tolov"].barh(tolov.index, tolov.values, color="#b06000") axd["tolov"].set_title("To'lov turi, mln so'm") kun = kunlik.groupby(kunlik.index.dayofweek).mean() axd["kun"].bar(["Du", "Se", "Ch", "Pa", "Ju", "Sh", "Ya"], kun.values, color="#137333") axd["kun"].set_title("O'rtacha kunlik, hafta kuni") soat = pd.to_datetime(savdo["vaqt"], format="%H:%M").dt.hour axd["soat"].hist(soat, bins=range(8, 23), color="#7b1fa2", rwidth=0.9) axd["soat"].set_title("Qatorlar soati") fig.suptitle("Do'kon tarmog'i: 2025 yil", fontsize=14, weight="bold") plt.show()

subplot_mosaic ga "rasm chizasiz": ro'yxat ichidagi har nom — bitta chizma, bir xil nom bir nechta katakni egallasa — chizma kengayadi. Natija — axd lug'at: axd["trend"]. Nomli chizmalar bilan kod axs[1, 2] dan ancha o'qilishi oson.
layout="constrained" — Matplotlib chizmalar orasidagi bo'shliqni o'zi hisoblaydi, sarlavha va yozuvlar bir-biriga minmaydi. Eski usul — fig.tight_layout() — ham ishlaydi, lekin constrained suptitle va legend lar bilan yaxshiroq.
Bo'sh chizmani yashirish
fig, axs = plt.subplots(2, 3, figsize=(10, 5), sharex=True, sharey=True) for ax, filial in zip(axs.flat, oylik.columns): ax.plot(oylik.index, oylik[filial], marker=".") ax.set_title(f"{filial}-filial") axs.flat[-1].set_visible(False) plt.show()

5 ta filial, 6 ta katak — oxirgisi bo'sh qoladi. set_visible(False) uni yashiradi; aks holda varaqda bo'sh ramka "nimadir chizilmadi" degan taassurot qoldiradi.
Xulosa
plt.subplots(q, u)—axs— NumPy array;axs.flatbilan sikl.fig.suptitle— butun varaq sarlavhasi.- Solishtirish uchun chizmalarda umumiy o'q:
sharey=True/sharex=True; bar grafikda o'q noldan. subplot_mosaic— har xil o'lchamli, nomli chizmalar.layout="constrained"— avtomatik bo'shliqlar; ortiqcha chizmaniset_visible(False).
Mashqlar
- 3×1 panjarada (bir ustun) uch filialning kunlik tushumini
sharex=Truebilan chizing. subplot_mosaicbilan chapda katta scatter, o'ngda ustma-ust ikki kichik histogramma bo'lgan maket yasang.- Nega
sharey=Trueni har xil birlikdagi chizmalarda (masalan, tushum va cheklar soni) ishlatib bo'lmaydi?
Javoblar
fig, axs = plt.subplots(3, 1, sharex=True).plt.subplot_mosaic([["scatter", "h1"], ["scatter", "h2"]]).- Umumiy o'q faqat bir xil birlikdagi (so'm bilan so'm) qiymatlarni solishtirishga ma'noli; so'm va dona bitta shkalada bo'lsa, bittasi tekis chiziq bo'lib ko'rinadi.
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.