fig, ax = plt.subplots()ile nesne yönelimli yolla grafik oluşturmak ve başlık, eksen etiketleri ve gösterge eklemek- Soruya uygun grafik türünü seçmek: çizgi, sütun, saçılım, histogram
- Histogram kutu sayısını Sturges ve Freedman–Diaconis kurallarıyla gerekçelendirmek
- Yanıltıcı grafikleri tanımak ve dürüst, okunaklı grafikler çizmek
1973'te istatistikçi Francis Anscombe dört küçük veri kümesi yayımladı: ortalamaları, varyansları, korelasyon katsayısı ve regresyon doğrusu neredeyse aynıydı. Ama grafikte biri bir doğru çevresine saçılmış, biri bir eğri boyunca dizilmiş, üçüncüsünde tek bir aykırı nokta her şeyi değiştiriyor, dördüncüsünde ise biri hariç tüm noktalar dikey bir çizgi üzerinde duruyor. Ders şu: sayılara güvenmeden önce veriye bakmak gerekir. Python'da bunun temel aracı matplotlib'dir.
Figure ve Axes: grafiğin yapısı
Figure resmin tamamı, yani “tuval”dir. Axes onun içindeki tek bir çizim alanıdır: eksenler, çizgiler, başlık, gösterge. Bir Figure birkaç Axes içerebilir. Metotların çoğu Axes'e aittir: ax.plot, ax.set_title, ax.legend.
matplotlib'in iki üslubu vardır: plt.plot(...) gibi kısa “pyplot” üslubu ve nesne yönelimli üslup. Her zaman ikincisiyle başla: fig, ax = plt.subplots(); böyle bir kod birkaç grafikte de anlaşılır kalır. Tarayıcıda resim kodun altında otomatik olarak görünür; bilgisayarında plt.show() bir pencere açar, fig.savefig('chart.png', dpi=200) ise dosyayı kaydeder.
import matplotlib.pyplot as plt
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
baku = [279, 153, 426, 390, 455, 510]
ganja = [150, 306, 168, 210, 240, 265]
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(months, baku, marker='o', label='Baku')
ax.plot(months, ganja, marker='s', linestyle='--', label='Ganja')
ax.set_title('Monthly revenue by branch, 2026')
ax.set_xlabel('Month')
ax.set_ylabel('Revenue, AZN')
ax.grid(alpha=0.3)
ax.legend()
plt.show()- Başlık — grafik neyi, nerede ve ne zaman gösteriyor.
- Birimli eksen etiketleri: “Revenue, AZN”, “Height, cm”.
- Gösterge (
legend) — birden fazla seri varsa. - Soluk ızgara (
grid(alpha=0.3)) — değerleri okumayı kolaylaştırır, dikkati dağıtmaz.
Grafik türünü seçmek
| Soru | Grafik | matplotlib |
|---|---|---|
| Zamanla nasıl değişiyor? | çizgi grafiği | ax.plot |
| Kategoriler nasıl karşılaştırılır? | sütun grafiği | ax.bar, ax.barh |
| İki sayısal değişken ilişkili mi? | saçılım grafiği | ax.scatter |
| Değerler nasıl dağılmış? | histogram, kutu grafiği | ax.hist, ax.boxplot |
import numpy as np
import matplotlib.pyplot as plt
products = np.array(['Coffee', 'Cake', 'Tea', 'Juice', 'Sandwich'])
revenue = np.array([564, 540, 378, 212, 305])
order = np.argsort(revenue)
fig, ax = plt.subplots(figsize=(6, 3.5))
bars = ax.barh(products[order], revenue[order], color='#4C72B0')
ax.bar_label(bars, fmt='%d AZN', padding=3)
ax.set_xlim(0, 680)
ax.set_xlabel('Revenue, AZN')
ax.set_title('Revenue by product, Q1 2026')
print(products[order][-1], revenue.max())
plt.show()▸ Beklenen çıktı
Coffee 564
Saçılım grafiği iki sayısal değişken arasındaki ilişkiyi gösterir. Renk üçüncü bir değişkeni taşıyabilir (c=, cmap=); np.polyfit(x, y, 1) ise en küçük kareler yöntemiyle eğilim doğrusunu bulur. Aşağıdaki veriler uydurmadır: dairenin alanı, oda sayısı ve fiyatı.
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(3)
area = rng.uniform(40, 140, 60)
rooms = np.clip(area // 30, 1, 4).astype(int)
price = 1.5 * area + 10 * rooms + rng.normal(0, 15, 60)
slope, intercept = np.polyfit(area, price, 1)
print(f'slope: {slope:.2f} thousand AZN per m2')
print(f'correlation r = {np.corrcoef(area, price)[0, 1]:.3f}')
fig, ax = plt.subplots(figsize=(6, 4))
points = ax.scatter(area, price, c=rooms, cmap='viridis', alpha=0.8)
xs = np.array([40, 140])
ax.plot(xs, slope * xs + intercept, color='red', label='trend line')
fig.colorbar(points, ax=ax, label='rooms')
ax.set_xlabel('Area, m²')
ax.set_ylabel('Price, thousand AZN')
ax.legend()
plt.show()▸ Beklenen çıktı
slope: 2.00 thousand AZN per m2 correlation r = 0.960
viridis renk skalası siyah-beyaz baskıda da, renk görme sorunu olan kişiler için de okunaklıdır. Korelasyon katsayısı r bir sonraki derste ayrıntılı olarak açıklanıyor.Histogram ve kutu sayısı
Histogram, değer eksenini eşit aralıklara (bins, kutular) böler ve her aralığa düşen gözlemleri sayar. Kutu sayısı çok azsa dağılımın biçimi kaybolur; çok fazlaysa grafik gürültülü bir “tarağa” döner. İki bilinen kural bir başlangıç noktası verir:
- kkutu sayısı (Sturges kuralı)
- hkutu genişliği (Freedman–Diaconis kuralı), verinin biriminde
- ngözlem sayısı
- IQRçeyrekler açıklığı Q3 − Q1
Sturges, yaklaşık normal ve çok büyük olmayan veriler için uygundur; Freedman–Diaconis aykırı değerlere karşı dayanıklıdır. ax.hist(x, bins='fd') ikincisini otomatik uygular.
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(42)
heights = rng.normal(170, 8, 500)
k = int(np.ceil(np.log2(heights.size))) + 1
print('Sturges bins:', k)
print(f'mean = {heights.mean():.1f} cm, std = {heights.std(ddof=1):.1f} cm')
fig, ax = plt.subplots(figsize=(6, 4))
ax.hist(heights, bins=k, edgecolor='white')
ax.axvline(heights.mean(), color='red', linestyle='--', label='mean')
ax.set_xlabel('Height, cm')
ax.set_ylabel('Number of people')
ax.legend()
plt.show()▸ Beklenen çıktı
Sturges bins: 10 mean = 169.9 cm, std = 7.7 cm
n = 500, boylar yaklaşık normal dağılmış, σ ≈ 8 cm. Sturges ve Freedman–Diaconis kurallarıyla kutuları hesapla. Normal dağılımda IQR ≈ 1,35σ.
Çözümü gösterÇözümü gizle
Freedman–Diaconis: IQR ≈ 1,35 · 8 = 10,8 cm; n^(1/3) = 500^(1/3) ≈ 7,94.
h = 2 · 10,8 / 7,94 ≈ 2,7 cm.
Aralık yaklaşık 170 ± 3σ, yani ~48 cm → 48 / 2,7 ≈ 18 kutu.
FD daha ince ayrıntı gösterir; n büyüdükçe Sturges kutu sayısını çok yavaş artırır.
- nᵢi. kutuya düşen gözlemler
- fᵢ
density=Trueile çubuk yüksekliği (yoğunluk) - hkutu genişliği
ax.hist(x, density=True) çubuk alanlarının toplamını 1 yapar; böyle bir histogram bir olasılık yoğunluğu eğrisiyle karşılaştırılabilir.
200 ölçüm, genişliği h = 2 olan kutulara ayrılmış. Bir kutuda 30 ölçüm var. density=True ile bu çubuğun yüksekliği nedir? Alanı neyi gösterir?
Çözümü gösterÇözümü gizle
Alan = f · h = 0,075 · 2 = 0,15; yani ölçümlerin %15'i bu kutuda (30 / 200).
Tüm çubukların alanlarının toplamı 1'dir (%100).
Tek şekilde birden fazla grafik
plt.subplots(2, 2) 2 × 2 boyutlu bir Axes dizisi döndürür; her grafiğe axes[satır, sütun] ile erişilir. layout='constrained' başlıkların ve eksenlerin üst üste binmesini önler, sharex=True ise eksenleri ortak yapar.
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(0)
x = np.linspace(0, 2 * np.pi, 100)
fig, axes = plt.subplots(2, 2, figsize=(8, 6), layout='constrained')
axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title('Line: sin x')
axes[0, 1].bar(['A', 'B', 'C'], [5, 3, 7])
axes[0, 1].set_title('Bar')
axes[1, 0].scatter(rng.random(30), rng.random(30))
axes[1, 0].set_title('Scatter')
axes[1, 1].hist(rng.normal(size=300), bins=15)
axes[1, 1].set_title('Histogram')
fig.suptitle('Four basic chart types')
print(axes.shape)
plt.show()▸ Beklenen çıktı
(2, 2)
pandas'ın matplotlib üzerine kurulu kendi .plot() metodu vardır: DataFrame'in her sütunu bir seri olur, indeks ise X eksenine yerleşir. Metot bir Axes döndürür; böylece grafiği sıradan matplotlib komutlarıyla tamamlayabilirsin.
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'month': ['Jan', 'Feb', 'Mar'],
'Baku': [279, 153, 426],
'Ganja': [150, 306, 168]}).set_index('month')
ax = df.plot(kind='bar', figsize=(6, 3.5), rot=0, title='Revenue by month, AZN')
ax.set_ylabel('AZN')
print(df.sum())
plt.show()▸ Beklenen çıktı
Baku 858 Ganja 624 dtype: int64
İyi bir grafiğin kuralları
- Bir grafik, bir fikir. Sonucu başlığa yaz: “Martta Bakü şubesi önde”.
- Sütun grafiğinde Y ekseni 0'dan başlamalıdır, çünkü göz çubuk uzunluklarını karşılaştırır.
- Renkler anlam taşısın: vurgulamak istediğin seriye parlak bir renk, diğerlerine gri ver.
- 3B efektlerden, gölgelerden ve çok dilimli pasta grafiklerinden kaçın; değerleri çarpıtırlar.
import matplotlib.pyplot as plt
branches = ['Baku', 'Ganja']
satisfied = [96, 98]
fig, (bad, good) = plt.subplots(1, 2, figsize=(8, 3.5), layout='constrained')
bad.bar(branches, satisfied, color=['gray', 'orange'])
bad.set_ylim(95, 98.5)
bad.set_title('Misleading: axis starts at 95')
good.bar(branches, satisfied, color=['gray', 'orange'])
good.set_ylim(0, 100)
good.set_title('Honest: axis starts at 0')
for ax in (bad, good):
ax.set_ylabel('Satisfied customers, %')
plt.show()revenue sözlüğünden yatay bir sütun grafiği (ax.barh) oluştur, başlığı 'Revenue by product' yap ve X eksenini 'AZN' olarak etiketle. Sonra ayrı satırlarda yazdır: 1) grafiğin başlığı (ax.get_title()); 2) grafikteki çubuk sayısı (len(ax.patches)); 3) geliri en yüksek ürün.
import matplotlib.pyplot as plt
revenue = {'Coffee': 564, 'Cake': 540, 'Tea': 378, 'Juice': 212, 'Sandwich': 305}
fig, ax = plt.subplots()
# draw the bars, set the title and the X label, then print the three results▸ Beklenen çıktı
Revenue by product 5 Coffee
Test puanlarının 5 kutulu histogramını oluştur. ax.hist üç şey döndürür: sayılar, kutu sınırları ve çubuklar. Ayrı satırlarda yazdır: 1) her kutudaki sayıyı tam sayılar listesi olarak; 2) bir kutunun genişliğini 2 ondalık basamağa yuvarlanmış olarak.
import matplotlib.pyplot as plt
scores = [55, 62, 68, 70, 71, 75, 78, 80, 82, 85, 88, 90, 94, 97]
fig, ax = plt.subplots()
# counts, edges, _ = ax.hist(...)▸ Beklenen çıktı
[2, 3, 3, 3, 3] 8.4
Önemli noktalar
- Figure resmin tamamı, Axes ise içindeki grafiktir;
fig, ax = plt.subplots()ile başla. - Zaman → çizgi, kategoriler → sütun, iki sayısal değişken → saçılım, dağılım → histogram.
- Her grafikte başlık, birimli eksen etiketleri ve gerektiğinde gösterge olmalıdır.
- Kutular: Sturges k = ⌈log₂ n⌉ + 1, Freedman–Diaconis h = 2 · IQR · n^(−1/3).
- Sütun grafiğinin ekseni 0'dan başlar; renk skalası için
viridisseç.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.