Birleştirme (merge, join, concat)
Önkoşul:groupby ve pivot
Kanca
Bir sipariş tablon var, bir de müşteri bilgi tablon. Sipariş tablosunda musteri_id=999 var ama bu müşteri, müşteri tablosunda kayıtlı değil (silinmiş hesap olabilir). İki tabloyu birleştirince bu sipariş ne olmalı — kaybolsun mu, yoksa müşteri bilgisi boş kalarak listede dursun mu? Cevap, hangi birleştirme türünü seçtiğine bağlı.
Sezgi
Gerçek veri neredeyse hiç tek bir tabloda durmaz — siparişler bir tabloda, müşteriler başka bir tabloda, ürünler başka bir tabloda olur. merge, iki tabloyu ORTAK BİR SÜTUNA (anahtar) göre yan yana birleştirir — SQL’deki JOIN ile aynı mantık. concat ise iki tabloyu ÜST ÜSTE (aynı sütunlarla) yığar — örneğin ocak ve şubat siparişlerini tek bir tabloda toplamak için.
merge’ün en kritik kararı how parametresidir: inner, sadece HER İKİ tabloda da bulunan anahtarları tutar; left, sol tablonun TAMAMINI korur, eşleşmeyen sağ taraf bilgisi boş (NaN) kalır.
Mekanizma
İki tablo kuralım — siparişlerin bazı müşteri numaraları, müşteri tablosunda yok:
İki ayrı tablo
# İki AYRI tablo: siparişler ve müşteriler. Bazı sipariş müşterileri, müşteri
# tablosunda YOK (örn. silinmiş hesap) — gerçek dünyada sık karşılaşılan bir durum.
siparisler = pd.DataFrame({
"siparis_no": [f"S{i}" for i in range(1, 9)],
"musteri_id": [101, 102, 103, 101, 104, 999, 102, 998], # 999 ve 998 müşteri tablosunda yok
"tutar": [149.9, 89.5, 320.0, 45.0, 210.75, 60.0, 180.0, 99.0],
})
musteriler = pd.DataFrame({
"musteri_id": [101, 102, 103, 104],
"segment": ["Sadık", "Yeni", "Sadık", "Yeni"],
"sehir": ["İstanbul", "Ankara", "İzmir", "Bursa"],
})
print("Siparişler:", siparisler.shape)
print("Müşteriler:", musteriler.shape)Siparişler: (8, 3)
Müşteriler: (4, 3)Şimdi iki farklı how ile birleştirelim:
inner vs left join
# INNER JOIN: sadece HER İKİ tabloda da olan musteri_id'ler kalır.
ic_birlesim = siparisler.merge(musteriler, on="musteri_id", how="inner")
print(f"\nInner join sonucu: {len(ic_birlesim)} satır (eşleşmeyenler düştü)")
print(ic_birlesim)
# LEFT JOIN: siparişlerin TAMAMI kalır, eşleşmeyen müşteri bilgisi NaN olur.
sol_birlesim = siparisler.merge(musteriler, on="musteri_id", how="left")
print(f"\nLeft join sonucu: {len(sol_birlesim)} satır (hiçbir sipariş kaybolmadı)")
print(sol_birlesim[["siparis_no", "musteri_id", "segment"]])
Inner join sonucu: 6 satır (eşleşmeyenler düştü)
siparis_no musteri_id tutar segment sehir
0 S1 101 149.90 Sadık İstanbul
1 S2 102 89.50 Yeni Ankara
2 S3 103 320.00 Sadık İzmir
3 S4 101 45.00 Sadık İstanbul
4 S5 104 210.75 Yeni Bursa
5 S7 102 180.00 Yeni Ankara
Left join sonucu: 8 satır (hiçbir sipariş kaybolmadı)
siparis_no musteri_id segment
0 S1 101 Sadık
1 S2 102 Yeni
2 S3 103 Sadık
3 S4 101 Sadık
4 S5 104 Yeni
5 S6 999 NaN
6 S7 102 Yeni
7 S8 998 NaNinner join’de 8 siparişten 6’sı kaldı — 999 ve 998 numaralı müşterilerin siparişleri (S6, S8) düştü, çünkü bu müşteriler musteriler tablosunda yok. left join’de ise 8 siparişin TAMAMI kaldı, sadece eşleşmeyen satırlarda segment sütunu NaN oldu.
Çoğu kişi “merge her zaman satır kaybetmez” ya da tam tersini, “merge her zaman tüm satırları korur” sanır. Değil, çünkü ikisi de how parametresine bağlı bir seçimdir — inner bilinçli olarak eşleşmeyenleri atar, left bilinçli olarak korur. Hangisini seçtiğin, “kaç sipariş kaybettim” sorusunun cevabını doğrudan değiştirir.
Matematik
merge türleri ve concat
| Tür | Ne tutulur |
|---|---|
inner | Sadece HER İKİ tabloda da bulunan anahtarlar |
left | Sol tablonun TÜM satırları; sağdan eşleşmeyen yerler NaN |
right | Sağ tablonun TÜM satırları; soldan eşleşmeyen yerler NaN |
outer | HER İKİ tablonun TÜM satırları; eşleşmeyen her iki yönde de NaN |
concat | Anahtar araması yapmaz — tabloları doğrudan üst üste (veya yan yana) yığar |
concat, merge’den kavramsal olarak farklıdır: merge “bu satır, o satırla nasıl eşleşiyor” sorusunu sorarken, concat sadece “bu tabloları birbirine ekle” der — aynı sütun yapısına sahip parçaları (örn. farklı ayların verisi) birleştirmek için idealdir.
Kod
concat ile iki ayrı ayın sipariş verisini birleştirelim:
concat ile üst üste birleştirme
# concat: iki tabloyu ÜST ÜSTE (aynı sütunlarla) birleştirmek — örn. iki ayrı ayın verisi.
ocak = pd.DataFrame({"siparis_no": ["S101", "S102"], "tutar": [120.0, 85.0], "ay": "Ocak"})
subat = pd.DataFrame({"siparis_no": ["S201", "S202"], "tutar": [95.0, 310.0], "ay": "Şubat"})
tum_yil = pd.concat([ocak, subat], ignore_index=True)
print(f"\nOcak: {len(ocak)} satır, Şubat: {len(subat)} satır, birleşim: {len(tum_yil)} satır")
print(tum_yil)
Ocak: 2 satır, Şubat: 2 satır, birleşim: 4 satır
siparis_no tutar ay
0 S101 120.0 Ocak
1 S102 85.0 Ocak
2 S201 95.0 Şubat
3 S202 310.0 ŞubatNerede işe yarar
Birleştirme, gerçek dünyadaki neredeyse her veri analizinin ilk adımlarından biridir:
- Çoklu tablo veritabanları. Siparişler, müşteriler, ürünler gibi ayrı tablolarda tutulan ilişkisel verileri tek bir analiz tablosuna toplamak.
- Zaman bazlı veri birleştirme. Farklı dönemlerden (aylık, yıllık) gelen dosyaları tek bir veri setinde toplamak (
concat). - Veri zenginleştirme. Bir ana tabloya, referans tablolardan (ülke kodları, kategori adları) ek bilgi eklemek.
Bu 3 hatayı yaparsın:
howparametresini düşünmeden varsayılanı (inner) kullanıp sessizce veri kaybetmek.- Birleştirme sonrası satır sayısını kontrol etmemek — beklenmedik bir artış, anahtar sütununda tekrarlanan değerler olduğunu gösterebilir.
concatilemerge’ü karıştırmak — concat anahtar araması yapmaz, sadece sütun yapısı uyan tabloları üst üste yığar.
Kendini test et
1. `inner` join ile `left` join arasındaki temel fark nedir?
- Aralarında fark yoktur
- inner sadece her iki tabloda da eşleşen anahtarları tutar, left sol tablonun tüm satırlarını korur (doğru cevap)
- left her zaman daha az satır döndürür
- inner sadece sayısal anahtarlarda çalışır
Neden: inner join eşleşmeyen satırları atar; left join sol tablonun tamamını korur ve eşleşmeyen sağ taraf bilgisini NaN ile doldurur.
2. Notebook örneğinde inner join sonrası neden 8 değil 6 satır kaldı?
- Hata oluştu
- 999 ve 998 numaralı müşteriler musteriler tablosunda olmadığı için o siparişler düştü (doğru cevap)
- pandas rastgele satır siler
- concat kullanıldığı için
Neden: inner join sadece HER İKİ tabloda da bulunan anahtarları tutar; 999 ve 998 müşteri tablosunda olmadığı için onlara ait siparişler sonuçtan düştü.
3. concat ile merge arasındaki temel fark nedir?
- Aynı işlevi görürler
- concat anahtar eşleştirmesi yapmadan tabloları üst üste yığar, merge ortak bir sütuna göre eşleştirir (doğru cevap)
- concat sadece sayısal verilerde çalışır
- merge sadece iki tablo ile çalışır, concat sınırsız
Neden: merge bir anahtar sütununa göre satırları eşleştirirken, concat hiçbir eşleştirme yapmadan tabloları doğrudan birbirine ekler (genelde aynı sütun yapısındaki parçaları birleştirmek için).
Özet
Özet
- merge, iki tabloyu ortak bir anahtar sütuna göre yan yana birleştirir — SQL JOIN mantığıyla.
- inner join sadece eşleşen anahtarları tutar; left join sol tablonun tamamını korur.
- concat, aynı sütun yapısındaki tabloları anahtar araması yapmadan üst üste yığar.
- how parametresini bilinçli seçmek, birleştirme sonrası kaç satırın kaldığını doğrudan belirler.
- Birleştirme sonrası satır sayısını her zaman kontrol etmek, beklenmedik veri kaybını veya çoğalmasını erken yakalar.