Takip et

Pandas DataFrame apply() Metodu Neden Bu Kadar Önemli?

Pandas DataFrame apply() Metodu Neden Bu Kadar Önemli?

Veri analizi ve manipülasyonu, günümüzün veri odaklı dünyasında hayati bir beceridir. Python ekosisteminde Pandas kütüphanesi, bu alanda adeta bir devrim yaratmıştır. Ancak bazen standart Pandas metotları, özel veya karmaşık veri dönüşüm ihtiyaçlarınızı karşılamakta yetersiz kalabilir. İşte tam bu noktada, Pandas DataFrame’in apply() metodu devreye girer. Bu güçlü araç, veri setleriniz üzerinde esnek ve özelleştirilmiş işlemler yapmanızı sağlayarak, veri temizleme, özellik mühendisliği ve karmaşık hesaplamaları çok daha erişilebilir hale getirir. Peki, bu metodun sunduğu esneklik ve gücü tam olarak nasıl kullanabiliriz ve veri işleme süreçlerimizi nasıl bir üst seviyeye taşıyabiliriz?

Pandas DataFrame, büyük veri setlerini tablo benzeri bir yapıda saklamak ve yönetmek için tasarlanmış iki boyutlu, boyut değiştirebilir, heterojen verili bir veri yapısıdır. Veri bilimciler ve analistler için vazgeçilmez bir araç olan DataFrame, verileri hızlı bir şekilde yükleme, filtreleme, sıralama ve özetleme gibi temel işlemleri kolaylaştırır. Ancak gerçek dünya verileri genellikle düzensizdir, eksik değerler içerir veya belirli bir formata dönüştürülmesi gereken karmaşık yapılar barındırır. Bu tür durumlarda, önceden tanımlanmış fonksiyonlar veya lambda ifadeleri kullanarak DataFrame’in satırları, sütunları veya hücreleri üzerinde özel işlemler gerçekleştirmek gerekebilir. İşte apply() metodu, bu özelleştirme ihtiyacını karşılamak için mükemmel bir çözüm sunar. Bu makalede, apply() metodunun derinliklerine inecek, farklı kullanım senaryolarını örneklerle açıklayacak ve veri işleme yeteneklerinizi nasıl geliştirebileceğinizi adım adım göstereceğiz. Hazırlanın, çünkü Pandas ile veri manipülasyonunda ustalığınızı artırmanın kapılarını aralıyoruz.

Veri setleri üzerinde karmaşık dönüşümler yapmak, genellikle bir dizi adım gerektirir. Örneğin, bir metin sütunundaki tüm kelimeleri küçük harfe çevirmek, belirli bir formattaki tarihleri standart bir formata dönüştürmek veya birden fazla sayısal sütunu kullanarak yeni bir skor hesaplamak gibi işlemler. Pandas’ın sağladığı vektörize operasyonlar bu görevlerin çoğunu hızla yerine getirebilirken, bazı durumlar daha fazla esneklik gerektirir. Özellikle, her bir satır veya sütun için özel koşulların uygulandığı, dış kütüphanelerle entegrasyon gerektiren veya karmaşık mantık içeren durumlarda apply() metodu öne çıkar. Bu metodun temel prensiplerini anlamak, veri analizi projelerinizde karşılaşabileceğiniz hemen her türlü özel dönüşüm sorununa çözüm bulmanızı sağlayacaktır. İlerleyen bölümlerde, apply()‘ın nasıl çalıştığını, hangi parametrelerle kullanılabileceğini ve gerçek dünya problemlerini çözmek için nasıl uygulanabileceğini detaylıca inceleyeceğiz.

Pandas apply() Metodu Nedir ve Nasıl Çalışır?

Pandas DataFrame’in apply() metodu, adından da anlaşılacağı gibi, bir fonksiyonu DataFrame’in satırlarına veya sütunlarına “uygulamak” için kullanılır. Bu, özellikle standart Pandas metotlarının yeterli olmadığı durumlarda, kendi özel mantığınızı veya dış kütüphanelerden gelen fonksiyonları entegre etmek istediğinizde inanılmaz derecede faydalıdır. Temel olarak, apply(), DataFrame’in her bir satırını veya sütununu bir Series objesi olarak alır ve tanımladığınız fonksiyonu bu Series objesi üzerinde çalıştırır. Sonuçlar daha sonra orijinal DataFrame’e entegre edilebilir veya yeni bir DataFrame/Series olarak döndürülebilir.

apply() metodunun en önemli parametrelerinden biri axis parametresidir. Bu parametre, fonksiyonun hangi eksen boyunca uygulanacağını belirtir:

  • axis=0 (varsayılan): Fonksiyonu her bir sütuna uygular. Fonksiyon, DataFrame’in her bir sütununu ayrı bir Series olarak alır.
  • axis=1: Fonksiyonu her bir satıra uygular. Fonksiyon, DataFrame’in her bir satırını ayrı bir Series olarak alır.

Bu eksen seçimi, yapacağınız işlemin doğasına göre kritik öneme sahiptir. Örneğin, bir sütundaki tüm değerleri belirli bir formata dönüştürmek istiyorsanız axis=0 kullanırken, bir satırdaki farklı sütun değerlerini birleştirerek yeni bir sonuç elde etmek istiyorsanız axis=1 kullanmanız gerekir. Fonksiyonunuz, tek bir değeri döndürebilir (bu durumda yeni bir Series veya DataFrame sütunu oluşur) veya birden fazla değeri döndürebilir (bu durumda yeni sütunlar veya bir DataFrame oluşur).

Şimdi basit bir örnekle apply() metodunun nasıl çalıştığını görelim. Diyelim ki elimizde öğrenci notlarını içeren bir DataFrame var ve her öğrencinin ortalama notunu hesaplamak istiyoruz:


import pandas as pd

# Örnek bir DataFrame oluşturalım
data = {
    'Öğrenci': ['Ali', 'Ayşe', 'Can'],
    'Matematik': [85, 92, 78],
    'Fizik': [70, 88, 95],
    'Kimya': [90, 75, 82]
}
df = pd.DataFrame(data)
print("Orijinal DataFrame:")
print(df)

# Her öğrencinin ortalama notunu hesaplayalım (satır bazında)
# Matematik, Fizik, Kimya sütunlarını seçip apply uygulayalım
df['Ortalama Not'] = df[['Matematik', 'Fizik', 'Kimya']].apply(lambda row: (row['Matematik'] + row['Fizik'] + row['Kimya']) / 3, axis=1)
print("\nOrtalama Not eklenmiş DataFrame:")
print(df)

Yukarıdaki örnekte, apply() metodunu axis=1 ile kullandık, bu da fonksiyonun her bir satır üzerinde çalışacağı anlamına geliyor. Lambda fonksiyonu, her bir satırı (row olarak temsil edilen bir Series) alarak ‘Matematik’, ‘Fizik’ ve ‘Kimya’ notlarını topluyor ve üçe bölerek ortalamayı buluyor. Bu yeni hesaplanan değerler, ‘Ortalama Not’ adında yeni bir sütun olarak DataFrame’e eklendi. Bu basit örnek bile, apply() metodunun veri manipülasyonu için ne kadar esnek bir araç olduğunu göstermektedir. İster basit bir aritmetik işlem, ister karmaşık bir koşullu mantık olsun, apply() sayesinde DataFrame’inizi istediğiniz gibi şekillendirebilirsiniz. Unutmayın, apply()‘ın gücü, ona ileteceğiniz fonksiyonun karmaşıklığıyla doğru orantılıdır.

DataFrame apply() ile Satır ve Sütun Bazında Dönüşümler Nasıl Yapılır?

Pandas DataFrame’deki apply() metodu, veri dönüşümlerini hem satır hem de sütun bazında gerçekleştirmek için oldukça esnek bir yapı sunar. Bu esneklik, veri analizinde karşılaşılan birçok özelleştirilmiş senaryoyu çözmek için kilit rol oynar. Doğru axis parametresi seçimiyle, belirli bir sütundaki değerleri tek tek işleyebilir veya birden fazla sütundaki değerleri bir araya getirerek yeni bir sonuç elde edebilirsiniz.

Sütun Bazında apply() Kullanımı (axis=0 veya varsayılan)

Varsayılan olarak axis=0 olduğunda, apply() metodu her bir sütunu ayrı ayrı ele alır. Fonksiyonunuz, her sütunu bir Pandas Series objesi olarak alır ve bu Series üzerinde işlem yapar. Bu kullanım, genellikle bir sütundaki tüm değerlere aynı dönüşümü uygulamak veya bir sütun için özet istatistikler hesaplamak istediğinizde tercih edilir. Örneğin, bir DataFrame’deki tüm sayısal sütunların karekökünü almak veya string sütunlardaki tüm değerleri büyük harfe çevirmek gibi işlemler için idealdir.


import pandas as pd
import numpy as np

data = {
    'A': [10, 20, 30],
    'B': [4, 5, 6],
    'C': ['elma', 'armut', 'çilek']
}
df = pd.DataFrame(data)
print("Orijinal DataFrame:")
print(df)

# Sütun A ve B'deki değerlerin karesini alalım (sayısal sütunlara özel)
df_kare = df[['A', 'B']].apply(lambda x: x**2)
print("\nSütun A ve B'nin karesi alınmış DataFrame:")
print(df_kare)

# Sütun C'deki string değerleri büyük harfe çevirelim
df['C_buyuk'] = df['C'].apply(lambda x: x.upper())
print("\nSütun C'deki değerleri büyük harfe çevrilmiş DataFrame:")
print(df)

Yukarıdaki örnekte, ilk apply() işlemi yalnızca ‘A’ ve ‘B’ sütunlarını etkilerken, ikinci apply() işlemi ‘C’ sütunundaki string değerleri dönüştürdü. Görüldüğü gibi, axis=0 (veya varsayılan) kullanıldığında, fonksiyon DataFrame’in her bir sütununa bağımsız olarak uygulanır ve her sütun bir Series olarak işlenir. Bu, veri setinizdeki her bir özelliğe (sütuna) özel dönüşümler uygulamak istediğinizde oldukça kullanışlıdır.

Satır Bazında apply() Kullanımı (axis=1)

axis=1 olarak ayarlandığında, apply() metodu her bir satırı bir Series objesi olarak alır ve tanımladığınız fonksiyonu bu satır üzerinde çalıştırır. Bu, özellikle birden fazla sütundaki değerleri birleştirerek yeni bir sonuç üretmek, satır bazında koşullu mantık uygulamak veya her satır için karmaşık hesaplamalar yapmak istediğinizde vazgeçilmezdir. Örneğin, bir e-ticaret sitesinin veri setinde, ‘sepetteki_ürün_sayısı’ ve ‘toplam_fiyat’ sütunlarına bakarak ‘indirim_uygulanmalı_mı’ gibi yeni bir özellik oluşturmak isteyebilirsiniz.


import pandas as pd

data = {
    'Ürün': ['Laptop', 'Mouse', 'Keyboard'],
    'Fiyat': [1200, 25, 75],
    'Adet': [1, 2, 1],
    'KDV_Oranı': [0.18, 0.18, 0.18]
}
df = pd.DataFrame(data)
print("Orijinal DataFrame:")
print(df)

# Her ürünün KDV dahil toplam fiyatını hesaplayalım (satır bazında)
def hesapla_kdv_dahil_fiyat(row):
    return row['Fiyat'] * row['Adet'] * (1 + row['KDV_Oranı'])

df['KDV_Dahil_Toplam'] = df.apply(hesapla_kdv_dahil_fiyat, axis=1)
print("\nKDV Dahil Toplam Fiyat eklenmiş DataFrame:")
print(df)

Bu örnekte, hesapla_kdv_dahil_fiyat adında bir fonksiyon tanımladık ve bu fonksiyonu axis=1 ile DataFrame’in her bir satırına uyguladık. Fonksiyon, her satırı (row) bir Series olarak alarak ‘Fiyat’, ‘Adet’ ve ‘KDV_Oranı’ sütunlarına erişiyor ve KDV dahil toplam fiyatı hesaplıyor. Sonuç olarak, ‘KDV_Dahil_Toplam’ adında yeni bir sütun oluştu. Satır bazında apply() kullanımı, özellikle veri setinizdeki farklı özellikler arasındaki ilişkileri kullanarak yeni, daha anlamlı özellikler türetmek istediğinizde müthiş bir güç sağlar. Bu sayede, karmaşık iş mantığını doğrudan Pandas DataFrame’inize entegre edebilirsiniz.

Hücre Bazında Uygulamalar: applymap() ve map() Metotları ile Karşılaştırma

Pandas, sadece satır ve sütun bazında değil, aynı zamanda hücre bazında da fonksiyon uygulama yetenekleri sunar. Bu, özellikle DataFrame’deki her bir elemanı tek tek dönüştürmeniz gerektiğinde çok kullanışlıdır. Bu tür işlemler için applymap() ve map() metotları devreye girer. Her iki metot da belirli senaryolarda apply()‘a alternatif veya tamamlayıcı olarak kullanılabilir, ancak kullanım amaçları ve kapsamları farklılık gösterir.

DataFrame.applymap(): Tüm Hücrelere Fonksiyon Uygulama

applymap() metodu, bir DataFrame’deki her bir hücreye, bağımsız olarak aynı fonksiyonu uygulamak için tasarlanmıştır. Bu, özellikle DataFrame’deki tüm elemanların veri tipini değiştirmek, string formatını güncellemek veya sayısal değerlere belirli bir matematiksel işlem uygulamak istediğinizde idealdir. applymap(), DataFrame’in tamamını veya belirli bir alt kümesini ele alarak her bir elemanı tek tek işler ve sonuç olarak orijinal DataFrame ile aynı boyutlarda yeni bir DataFrame döndürür.


import pandas as pd

data = {
    'A': [1, 2, 3],
    'B': [4, 5, 6],
    'C': ['x', 'y', 'z']
}
df = pd.DataFrame(data)
print("Orijinal DataFrame:")
print(df)

# Tüm sayısal hücrelere 10 ekleyelim
df_artı_on = df.applymap(lambda x: x + 10 if isinstance(x, (int, float)) else x)
print("\nSayısal hücrelere 10 eklenmiş DataFrame:")
print(df_artı_on)

# Tüm string hücreleri büyük harfe çevirelim
df_buyuk_harf = df.applymap(lambda x: str(x).upper() if isinstance(x, str) else x)
print("\nString hücreleri büyük harfe çevrilmiş DataFrame:")
print(df_buyuk_harf)

Bu örneklerde, applymap() kullanarak sayısal değerlere işlem uyguladık ve string değerleri dönüştürdük. applymap()‘ın temel farkı, fonksiyonu her bir elemana uygularken, apply()‘ın bir Series (satır veya sütun) üzerinde çalışmasıdır. Bu da applymap()‘ı, veri tiplerinden bağımsız olarak her hücrede tekil işlemler yapmak istediğinizde daha uygun bir seçenek haline getirir.

Series.map(): Tek Bir Series’e (Sütuna) Fonksiyon Uygulama

map() metodu, bir Series objesi (yani tek bir DataFrame sütunu) üzerindeki her elemana bir fonksiyon veya bir sözlük (dictionary) uygulamak için kullanılır. map(), özellikle bir sütundaki değerleri başka bir değerle eşlemek (mapping) veya o sütundaki her bir elemana özel bir dönüşüm uygulamak istediğinizde çok etkilidir. map(), DataFrame’in tamamı yerine yalnızca belirli bir sütun üzerinde çalışır ve sonuç olarak yeni bir Series döndürür.


import pandas as pd

data = {
    'Ürün Kodu': ['A1', 'B2', 'A1', 'C3', 'B2'],
    'Fiyat': [100, 200, 105, 300, 210]
}
df = pd.DataFrame(data)
print("Orijinal DataFrame:")
print(df)

# Ürün kodlarını tam isimleriyle eşleyelim (sözlük kullanarak)
urun_esleme = {'A1': 'Laptop', 'B2': 'Mouse', 'C3': 'Klavye'}
df['Ürün Adı'] = df['Ürün Kodu'].map(urun_esleme)
print("\nÜrün Adı eklenmiş DataFrame (map ile sözlük eşlemesi):")
print(df)

# Fiyatları yuvarlayalım (fonksiyon kullanarak)
df['Yuvarlanmış Fiyat'] = df['Fiyat'].map(lambda x: round(x, -1)) # En yakın 10'a yuvarla
print("\nYuvarlanmış Fiyat eklenmiş DataFrame (map ile fonksiyon):")
print(df)

Bu örnekte, map() metodunu hem bir sözlük ile değerleri eşlemek hem de bir lambda fonksiyonu ile sayısal değerleri dönüştürmek için kullandık. map(), tek bir sütun üzerinde hızlı ve etkili dönüşümler yapmak için idealdir. Özellikle kategorik verileri kodlamak veya belirli değerleri değiştirmek istediğinizde güçlü bir araçtır.

apply(), applymap() ve map() Arasındaki Farklar ve Ne Zaman Hangisini Kullanmalı?

Bu üç metot arasındaki temel farkları özetlemek gerekirse:

  • apply(): DataFrame’in satırlarına (axis=1) veya sütunlarına (axis=0) fonksiyon uygular. Fonksiyon, bir Series objesi alır ve bir Series, DataFrame veya tek bir değer döndürebilir. Karmaşık, çoklu sütun/satır bağımlı işlemler için en uygunudur.
  • applymap(): DataFrame’deki her bir elemana (hücreye) fonksiyon uygular. Fonksiyon, tek bir değer alır ve tek bir değer döndürür. Veri tipinden bağımsız olarak tüm hücrelerde tekil dönüşümler için idealdir.
  • map(): Yalnızca bir Series (tek bir sütun) üzerindeki her bir elemana fonksiyon veya sözlük uygular. Fonksiyon, tek bir değer alır ve tek bir değer döndürür. Belirli bir sütundaki değerleri eşlemek veya dönüştürmek için en hızlı ve en etkili yoldur.

Genel olarak, eğer işleminiz vektörize edilebiliyorsa (yani Pandas’ın veya NumPy’ın yerleşik hızlı metotları ile yapılabilirse), o metotları tercih etmek her zaman en iyisidir. Ancak, özel bir mantık, koşullu işlemler veya dış kütüphane entegrasyonu gerektiğinde, bu üç metot size inanılmaz bir esneklik sunar. Seçiminiz, işleminizin kapsamına (tüm DataFrame, tek bir sütun, tek bir hücre) ve fonksiyonunuzun aldığı girdi/çıktı tipine bağlı olacaktır.

Gerçek Dünya Senaryolarında apply() Kullanımı: Vaka Analizleri

apply() metodu, soyut kavramlardan çok, gerçek dünya problemlerini çözmede pratik uygulamalarıyla öne çıkar. Veri bilimciler ve analistler, karmaşık veri temizleme, özellik mühendisliği ve iş mantığı entegrasyonu gibi görevlerde sıkça apply()‘a başvururlar. İşte apply()‘ın gücünü gösteren iki gerçek dünya vaka analizi.

Vaka 1: Müşteri Segmentasyonu için Puanlama Sistemi Oluşturma

Bir perakende şirketinin müşteri verilerini analiz ettiğimizi düşünelim. Amacımız, müşterileri davranışlarına göre segmentlere ayırmak için bir puanlama sistemi oluşturmak. Bu puanlama, müşterinin yaşına, son satın alma tarihine (eskiliğine) ve toplam harcama miktarına göre belirlenecek. Her bir faktörün farklı bir ağırlığı olacak ve bu faktörleri birleştirerek tek bir ‘Müşteri Değeri Skoru’ elde edeceğiz.


import pandas as pd
from datetime import datetime

# Örnek müşteri verisi
data = {
    'Müşteri_ID': [101, 102, 103, 104, 105],
    'Yaş': [30, 45, 22, 55, 38],
    'Son_Satın_Alma_Tarihi': ['2023-10-15', '2023-01-20', '2024-03-01', '2022-07-10', '2023-11-25'],
    'Toplam_Harcama': [500, 1200, 150, 2000, 750]
}
df = pd.DataFrame(data)

# Tarih sütununu datetime objesine dönüştürelim
df['Son_Satın_Alma_Tarihi'] = pd.to_datetime(df['Son_Satın_Alma_Tarihi'])

# Bugünün tarihini belirleyelim (simülasyon için)
bugun = datetime(2024, 4, 1)

print("Orijinal Müşteri DataFrame:")
print(df)

# Müşteri Değeri Skoru hesaplayan fonksiyon
def hesapla_musteri_degeri_skoru(row):
    yas_agirlik = 0.3
    eskilik_agirlik = 0.4
    harcama_agirlik = 0.3

    # Yaş puanı (yaş arttıkça puan düşsün, genç müşteriler daha değerli kabul edilsin)
    yas_puani = max(0, 100 - (row['Yaş'] - 18) * 2) # 18 yaş 100 puan, 68 yaş 0 puan

    # Eskilik puanı (son satın alma tarihi ne kadar yakınsa o kadar yüksek puan)
    eskilik_gun = (bugun - row['Son_Satın_Alma_Tarihi']).days
    eskilik_puani = max(0, 100 - eskilik_gun / 5) # Her 5 gün için 1 puan düşsün

    # Harcama puanı (toplam harcama ne kadar yüksekse o kadar yüksek puan)
    harcama_puani = min(100, row['Toplam_Harcama'] / 20) # 2000 harcama 100 puan

    # Ağırlıklı ortalama ile genel skor
    genel_skor = (yas_puani * yas_agirlik +
                  eskilik_puani * eskilik_agirlik +
                  harcama_puani * harcama_agirlik)
    return round(genel_skor, 2)

# apply() metodunu kullanarak 'Müşteri_Değeri_Skoru' sütununu oluşturalım
df['Müşteri_Değeri_Skoru'] = df.apply(hesapla_musteri_degeri_skoru, axis=1)

print("\nMüşteri Değeri Skoru eklenmiş DataFrame:")
print(df)

Bu vaka analizinde, hesapla_musteri_degeri_skoru adında özel bir fonksiyon tanımladık. Bu fonksiyon, her bir müşteri satırını (row) girdi olarak alır ve ‘Yaş’, ‘Son_Satın_Alma_Tarihi’ ve ‘Toplam_Harcama’ sütunlarını kullanarak belirli bir mantıkla puanlar hesaplar. Ardından, bu puanları ağırlıklandırarak tek bir ‘Müşteri Değeri Skoru’ oluşturur. df.apply(hesapla_musteri_degeri_skoru, axis=1) ifadesi, bu fonksiyonu DataFrame’deki her bir müşteri kaydına (satırına) uygulayarak, karmaşık bir iş mantığını tek bir satır kodla entegre etmemizi sağlar. Bu tür puanlama sistemleri, pazarlama kampanyalarını hedeflemede, müşteri sadakat programlarını geliştirmede ve risk değerlendirmesinde kritik rol oynar.

Vaka 2: Metin Verilerinde Temizleme ve Özellik Çıkarma

Doğal Dil İşleme (NLP) projelerinde, metin verilerini ön işlemek ve onlardan anlamlı özellikler çıkarmak sıkça karşılaşılan bir görevdir. Çoğu zaman metinler özel karakterler, gereksiz boşluklar veya standart olmayan formatlar içerir. apply() metodu, bu tür metin temizleme ve özellik çıkarma işlemlerini otomatikleştirmek için çok güçlü bir araçtır.


import pandas as pd
import re # Düzenli ifadeler için

# Örnek metin verisi
data = {
    'ID': [1, 2, 3],
    'Metin': [
        '  Merhaba Dünya! Bu bir test metnidir.  ',
        'Python & Pandas çok güçlüdür!!!',
        'Veri Bilimi Harika.'
    ]
}
df = pd.DataFrame(data)
print("Orijinal Metin DataFrame:")
print(df)

# Metin temizleme ve özellik çıkarma fonksiyonu
def metin_isleme(text):
    # 1. Küçük harfe çevir
    text = text.lower()
    # 2. Özel karakterleri kaldır (harf ve sayı dışındakiler)
    text = re.sub(r'[^a-z0-9\s]', '', text)
    # 3. Birden fazla boşluğu tek boşluğa indir
    text = re.sub(r'\s+', ' ', text)
    # 4. Başlangıç ve sondaki boşlukları kaldır
    text = text.strip()
    return text

# apply() metodunu kullanarak 'Temizlenmiş_Metin' sütununu oluşturalım
df['Temizlenmiş_Metin'] = df['Metin'].apply(metin_isleme)

# Kelime sayısını hesaplayan fonksiyon
def kelime_sayisi_hesapla(text):
    return len(text.split())

# apply() metodunu kullanarak 'Kelime_Sayısı' sütununu oluşturalım
df['Kelime_Sayısı'] = df['Temizlenmiş_Metin'].apply(kelime_sayisi_hesapla)

print("\nTemizlenmiş Metin ve Kelime Sayısı eklenmiş DataFrame:")
print(df)

Bu örnekte, önce metin_isleme adında bir fonksiyon tanımladık. Bu fonksiyon, bir metin dizesini alarak onu küçük harfe çevirir, özel karakterleri kaldırır, fazla boşlukları düzenler ve baştaki/sondaki boşlukları temizler. Daha sonra bu fonksiyonu ‘Metin’ sütununa apply() metodu ile uygulayarak ‘Temizlenmiş_Metin’ adında yeni bir sütun oluşturduk. Ardından, temizlenmiş metinler üzerinde kelime_sayisi_hesapla fonksiyonunu uygulayarak her bir metnin kelime sayısını çıkardık. Bu vaka, apply()‘ın metin verileri üzerinde karmaşık ve adım adım işlemler gerçekleştirmek için ne kadar etkili olduğunu göstermektedir. Özellikle NLP pipelinelarında, metinlerin standart bir formata getirilmesi ve çeşitli özelliklerin çıkarılması için apply() vazgeçilmez bir araçtır.

apply() Metodunun Performans İpuçları ve Alternatifleri

Pandas’ın apply() metodu, esneklik ve özelleştirme açısından çok güçlü olsa da, performans konusunda bazı sınırlamaları olabilir. Özellikle çok büyük veri setleriyle çalışırken veya yoğun hesaplamalar içeren fonksiyonlar uygularken, apply()‘ın döngü tabanlı yapısı nedeniyle yavaş çalıştığını fark edebilirsiniz. Bu bölümde, apply()‘ın performansını optimize etme yollarını ve daha hızlı alternatifleri inceleyeceğiz.

apply() Neden Yavaş Olabilir?

apply() metodu, Python’ın saf döngülerinden daha hızlı olsa da, Pandas’ın optimize edilmiş, vektörize edilmiş operasyonlarına göre genellikle daha yavaştır. Bunun temel nedeni, apply()‘ın Python seviyesinde bir fonksiyonu her bir satır veya sütun için ayrı ayrı çağırmasıdır. Bu “Python döngüsü” overhead’i, C veya Fortran gibi düşük seviyeli dillerde optimize edilmiş NumPy veya Pandas iç operasyonlarına kıyasla performansı düşürür.

Performans İpuçları ve Alternatifler

  1. Vektörize Pandas Metotlarını Tercih Edin:

    Eğer yapacağınız işlem Pandas’ın yerleşik vektörize metotlarıyla (örneğin .str accessor, .dt accessor, sayısal operasyonlar, fillna(), replace(), clip() vb.) yapılabiliyorsa, her zaman bunları tercih edin. Bu metotlar C dilinde optimize edilmiştir ve çok daha hızlı çalışır.

    
    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame({'A': np.random.rand(100000), 'B': np.random.rand(100000)})
    
    # apply() ile karekök alma (yavaş)
    # %timeit df['A'].apply(np.sqrt) # Örnek: 100 ms civarı
    
    # Vektörize NumPy ile karekök alma (hızlı)
    # %timeit np.sqrt(df['A']) # Örnek: 1 ms civarı
    
    # String işlemleri için .str accessor
    df_str = pd.DataFrame({'Text': ['  hello world  ', '  python rocks!  ']})
    # apply() ile (yavaş)
    # df_str['Text'].apply(lambda x: x.strip().upper())
    # Vektörize .str ile (hızlı)
    df_str['Text'].str.strip().str.upper()
            

    Görüldüğü gibi, vektörize işlemler performansta devasa farklar yaratabilir.

  2. NumPy Ufuncs Kullanın:

    NumPy’ın evrensel fonksiyonları (ufuncs), diziler üzerinde eleman bazında hızlı işlemler yapmak için tasarlanmıştır. Eğer fonksiyonunuz basit matematiksel veya mantıksal bir işlemse, bunu doğrudan NumPy ufunc’ları ile uygulamak apply()‘dan çok daha hızlı olacaktır.

    
    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame({'Sayı': [1, 4, 9, 16, 25]})
    
    # apply() ile
    df['Karekök_Apply'] = df['Sayı'].apply(np.sqrt)
    
    # NumPy ufunc ile
    df['Karekök_NumPy'] = np.sqrt(df['Sayı'])
    print(df)
            
  3. .transform() Metodu:

    Eğer groupby() işlemi sonrası her gruba bir fonksiyon uygulamak ve sonuçları orijinal DataFrame’in boyutuyla eşleştirmek istiyorsanız, apply() yerine .transform() metodunu kullanmayı düşünebilirsiniz. transform(), apply()‘a göre genellikle daha performanslıdır, çünkü Pandas’ın iç optimizasyonlarından daha fazla faydalanır ve genellikle tek bir değer yerine aynı boyutlarda bir Series döndürür.

    
    import pandas as pd
    
    df = pd.DataFrame({'Grup': ['A', 'B', 'A', 'B'], 'Değer': [10, 20, 15, 25]})
    
    # Her grubun ortalamasını alıp orijinal DataFrame'e ekleme
    df['Grup_Ortalaması'] = df.groupby('Grup')['Değer'].transform('mean')
    print(df)
            
  4. swifter Kütüphanesi:

    Bazı durumlarda, vektörize bir çözüm bulmak zor olabilir veya fonksiyonunuz çok karmaşık olabilir. Bu gibi durumlarda, swifter gibi üçüncü taraf kütüphaneler, apply() işlemlerini otomatik olarak hızlandırmak için paralel işlem veya Dask gibi araçları kullanabilir. Kurulumu basit olup, df.swifter.apply() şeklinde kullanılır.

    
    # import swifter # Kurulum: pip install swifter
    # df['Yeni_Sütun'] = df.swifter.apply(your_complex_function, axis=1)
            

    Bu, özellikle CPU yoğun işlemler için önemli performans artışları sağlayabilir.

  5. Named Fonksiyonlar ve Lambda İfadeleri:

    Lambda ifadeleri kısa ve okunabilir olsa da, çok karmaşık mantıklar için named (adlandırılmış) fonksiyonlar yazmak daha iyi bir uygulama olabilir. Performans açısından genellikle büyük bir fark yaratmazken, kodun okunabilirliğini ve bakımını artırır.

  6. Özetle, apply() metodunu kullanmadan önce her zaman vektörize Pandas veya NumPy metotlarını araştırmalısınız. Eğer vektörize bir çözüm mümkün değilse veya çok karmaşıksa, apply() hala güçlü bir seçenektir. Ancak bu durumda, performans beklentilerinizi gerçekçi tutmalı ve büyük veri setleri için alternatif hızlandırma tekniklerini (örneğin swifter) değerlendirmelisiniz. Doğru aracı doğru zamanda kullanmak, veri işleme süreçlerinizin hem verimli hem de anlaşılır olmasını sağlayacaktır.

    Sıkça Sorulan Sorular (SSS)

    Pandas DataFrame’in apply() metodu hakkında sıkça karşılaşılan bazı sorular ve cevapları aşağıdadır:

    • apply() metodu ne zaman kullanılmalı?

      apply() metodu, standart Pandas veya NumPy’nin vektörize metotlarının yeterli olmadığı durumlarda, özel bir fonksiyonu DataFrame’in satırları veya sütunları üzerinde çalıştırmak istediğinizde kullanılmalıdır. Özellikle karmaşık koşullu mantık, dış kütüphanelerle entegrasyon veya birden fazla sütunu içeren özel hesaplamalar gerektiğinde idealdir.

    • apply() metodu neden yavaş olabilir?

      apply(), Python seviyesinde bir fonksiyonu her bir satır veya sütun için ayrı ayrı çağırır. Bu, Pandas’ın C dilinde optimize edilmiş vektörize operasyonlarına kıyasla “Python döngüsü” overhead’i nedeniyle daha yavaş çalışmasına neden olabilir. Büyük veri setleri veya yoğun hesaplamalar içeren fonksiyonlar için bu performans farkı belirgin hale gelir.

    • apply() metodu ile birden fazla değer döndürmek mümkün mü?

      Evet, apply() metoduna ilettiğiniz fonksiyon bir Series veya liste döndürüyorsa, apply() bu sonuçları otomatik olarak birden fazla yeni sütun olarak DataFrame’e ekleyebilir. Bunun için genellikle result_type='expand' parametresini kullanmanız gerekebilir, özellikle axis=1 ile çalışırken.

      
      import pandas as pd
      df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
      def coklu_deger_dondur(row):
          return pd.Series([row['A'] + row['B'], row['A'] * row['B']], index=['Toplam', 'Çarpım'])
      df_yeni = df.apply(coklu_deger_dondur, axis=1)
      print(df_yeni)
              
    • apply() metodu groupby() ile nasıl kullanılır?

      groupby() ile apply() kullanmak, gruplar üzerinde karmaşık, özel dönüşümler yapmak için çok güçlü bir kombinasyondur. groupby() sonrası apply() çağrıldığında, fonksiyonunuz her bir grup için ayrı ayrı çağrılır ve o grubun DataFrame’ini girdi olarak alır.

      
      import pandas as pd
      df = pd.DataFrame({'Grup': ['A', 'B', 'A', 'B'], 'Değer': [10, 20, 15, 25]})
      def grup_ozet(group_df):
          return group_df['Değer'].max() - group_df['Değer'].min()
      sonuc = df.groupby('Grup').apply(grup_ozet)
      print(sonuc)
              
    • apply() ve transform() arasındaki fark nedir?

      Her ikisi de groupby() ile kullanılabilse de, temel farkları çıktı boyutlarındadır:

      • apply(): Her grup için rastgele boyutlarda bir sonuç döndürebilir (tek bir değer, Series, DataFrame). Bu sonuçlar daha sonra birleştirilir.
      • transform(): Her grup için tek bir değer veya orijinal grubun boyutuyla aynı boyutta bir Series döndürmelidir. Çıktı, orijinal DataFrame ile aynı indekslere ve boyuta sahip olacak şekilde yayınlanır. transform() genellikle apply()‘dan daha performanslıdır, çünkü daha kısıtlı bir çıktı yapısına sahiptir ve Pandas’ın iç optimizasyonlarından daha fazla yararlanabilir.

    Sonuç: Pandas apply() ile Veri Manipülasyonunda Ustalık

    Pandas DataFrame’in apply() metodu, veri analizi ve manipülasyonu dünyasında vazgeçilmez bir araçtır. Bu makale boyunca, apply()‘ın temel prensiplerinden başlayarak, satır ve sütun bazında nasıl kullanılabileceğine, applymap() ve map() gibi benzer metotlarla karşılaştırmalarına ve gerçek dünya senaryolarındaki pratik uygulamalarına kadar birçok yönünü detaylıca inceledik. Müşteri segmentasyonundan metin temizlemeye kadar çeşitli vaka analizleri, apply()‘ın karmaşık iş mantığını veri setlerinize nasıl entegre edebileceğinizi net bir şekilde ortaya koydu.

    Özellikle, apply()‘ın esnekliği, standart Pandas metotlarının yetersiz kaldığı durumlarda kendi özel fonksiyonlarınızı veya dış kütüphaneleri entegre etme yeteneğinden gelir. Bu sayede, veri setlerinizi istediğiniz formata dönüştürebilir, yeni ve anlamlı özellikler türetebilir ve veri odaklı kararlar almak için gerekli ön işlemleri yapabilirsiniz. Ancak, performansın kritik olduğu durumlarda, apply()‘ın vektörize Pandas veya NumPy metotlarına göre daha yavaş çalışabileceğini unutmamak önemlidir. Bu nedenle, her zaman önce vektörize çözümleri araştırmalı, eğer mümkün değilse apply()‘a başvurmalı ve gerekirse swifter gibi kütüphanelerle performansı optimize etmeyi düşünmelisiniz.

    Veri bilimindeki yolculuğunuzda, apply() metoduna hakim olmak, karşılaştığınız hemen her türlü veri manipülasyonu sorununa yaratıcı ve etkili çözümler üretmenizi sağlayacaktır. Bu güçlü aracın inceliklerini anlamak, sadece kod yazma becerilerinizi geliştirmekle kalmayacak, aynı zamanda veri setlerinizden daha derinlemesine içgörüler elde etmenize de yardımcı olacaktır. Unutmayın, en iyi veri bilimcisi, elindeki araçları en iyi şekilde tanıyan ve doğru aracı doğru problem için kullanabilen kişidir. Pandas apply() ile veri manipülasyonunda ustalaşarak, bu yetkinliğinizi bir adım öteye taşıyın ve veri dünyasındaki potansiyelinizi tam olarak açığa çıkarın.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.