İçeriğe geç
Educora
Üniversite25 dk33 / 42

matplotlib ile görselleştirme

Çizgi, sütun ve saçılım grafikleri, histogramlar ve alt grafikler oluştur; eksenleri, başlıkları ve göstergeleri doğru etiketle, kutu sayısını seç ve dürüst, okunaklı grafiklerin kurallarını öğren.

Kendini test et
Bu derste öğreneceklerin
  • 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ı

Tanım
Figure ve Axes

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.

Python
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()
Çizgi grafiği zaman içindeki değişimi gösterir. İşaretçiler ölçüm noktalarını gösterir; farklı çizgi stilleri ise renkleri ayırt edemeyenler için bile serileri ayırır.
  • 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

SoruGrafikmatplotlib
Zamanla nasıl değişiyor?çizgi grafiğiax.plot
Kategoriler nasıl karşılaştırılır?sütun grafiğiax.bar, ax.barh
İki sayısal değişken ilişkili mi?saçılım grafiğiax.scatter
Değerler nasıl dağılmış?histogram, kutu grafiğiax.hist, ax.boxplot
Python
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ı.

Python
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:

k = ⌈log₂ n⌉ + 1 h = 2 · IQR · n^(−1/3)
burada:
  • 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.

Python
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
Örnek 1: 500 kişinin boyu için kutular

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
Sturges: log₂ 500 ≈ 8,97 → ⌈8,97⌉ = 9 → k = 9 + 1 = 10 kutu (koddaki gibi).
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.
fᵢ = nᵢ / (n · h) ∑ fᵢ · h = 1fᵢ = nᵢ / (n · h) ∑ fᵢ · h = 1
burada:
  • nᵢi. kutuya düşen gözlemler
  • fᵢdensity=True ile ç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.

Örnek 2: yoğunluk histogramı

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
f = 30 / (200 · 2) = 0,075.
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.

Python
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.

Python
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ı

  1. Bir grafik, bir fikir. Sonucu başlığa yaz: “Martta Bakü şubesi önde”.
  2. Sütun grafiğinde Y ekseni 0'dan başlamalıdır, çünkü göz çubuk uzunluklarını karşılaştırır.
  3. Renkler anlam taşısın: vurgulamak istediğin seriye parlak bir renk, diğerlerine gri ver.
  4. 3B efektlerden, gölgelerden ve çok dilimli pasta grafiklerinden kaçın; değerleri çarpıtırlar.
Python
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()
Solda Gence'nin çubuğu Bakü'nünkünden üç kat uzun görünüyor, oysa fark yalnızca 2 yüzde puanı.
Alıştırma

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.

Alıştırma · Python
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
Alıştırma

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.

Alıştırma · Python
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 viridis seç.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
Beş şubenin yıllık gelirini karşılaştırmak için en uygun grafik hangisidir?