Pandas'ta tarih sütunları ve zaman serisi verisi adım adım nasıl işlenir?
Beceri rehberi

Pandas'ta tarih sütunları ve zaman serisi verisi adım adım nasıl işlenir?

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 7 dk okuma

to_datetime, resample, shift ve rolling ile pandas'ta tarih verisini temizleyin, dönemsel özetleyin ve zaman serisi hatalarından kaçının.

Zaman serisi işlemine başlamadan önce: sütun gerçekten tarih mi?

Tarihle ilgili hataların büyük kısmı tek bir yerden çıkar: tarih sütunu metin (object) olarak okunmuştur ve pandas bunu tarih saymaz. Metin olarak duran bir tarihi sıralarsanız gün sırasına göre değil alfabetik sıraya göre dizilir, iki tarih arasındaki farkı alamazsınız, aylık toplam çıkaramazsınız. İlk iş bu yüzden veri tipine bakmaktır: df.dtypes çıktısında tarih sütunu datetime64 olarak görünmüyorsa dönüştürme gerekir.

Dönüştürmenin temel aracı pd.to_datetime fonksiyonudur. Gün.ay.yıl biçiminde gelen Türkçe dosyalarda iki parametre belirleyicidir: format ile tam biçimi söylersiniz, örneğin format="%d.%m.%Y", ya da dayfirst=True ile gün önde okumasını istersiniz. Biçimi belirtmezseniz pandas tahmin yürütür ve on ikinci günden küçük günlerde gün ile ayı karıştırabilir. Bu sessiz bir hatadır: kod çalışır, sonuç yanlıştır.

Kirli verilerde errors="coerce" kullanın. Çözümlenemeyen her hücre NaT (not a time, tarihin eksik değeri) olur ve kod patlamaz; sonra df[df["tarih"].isna()] ile hangi satırların bozuk olduğunu listeleyip kaynağa dönersiniz. Varsayılan davranış errors="raise" olduğundan tek bir bozuk hücre tüm dönüşümü durdurur. Dönüştürülen sütunu geri yazmayı unutmayın: df["tarih"] = pd.to_datetime(df["tarih"], format="%d.%m.%Y", errors="coerce").

Tarih sütununu index yapmak ve dilimlemek

Zaman serisi çalışmasının ikinci adımı tarihi satır etiketi, yani index yapmaktır: df = df.set_index("tarih").sort_index(). Sıralama önemlidir; tarih index'i sıralı değilse dilimleme ve resample beklenmedik sonuç verir. Index artık bir DatetimeIndex olduğundan pandas'ın en kullanışlı özelliği açılır: kısmi metinle dilimleme.

ISO biçiminde yıl ya da yıl-ay yazarak o döneme ait tüm satırları alırsınız: df.loc["yıl"], df.loc["yıl-ay"] gibi (yerine gerçek yıl ve ay değerini koyarsınız). Aralık için df.loc["başlangıç":"bitiş"] kullanılır ve resmî belgede belirtildiği gibi iki uç da dahildir; bitiş olarak yalnızca günü yazarsanız o günün tamamı gelir. Belirli bir dakikayı seçerken sütun seçimiyle karışmasın diye her zaman .loc kullanın.

Index yerine sütunda kalmasını istediğiniz durumlarda .dt erişimcisi devreye girer. df["tarih"].dt.year, .dt.month, .dt.day_name() gibi özellikler yeni sütun türetmenizi sağlar. Haftanın günü ya da çeyrek gibi türetilmiş sütunlar satış analizinde kırılım için sık kullanılır: hafta içi ile hafta sonunu, ay başı ile ay sonunu karşılaştırmak için önce bu sütunları üretirsiniz, sonra groupby ile özetlersiniz.

Düzenli bir takvim oluşturmak: date_range ve eksik günler

Gerçek veride bazı günler yoktur: hafta sonu işlem yapılmaz, bir sensör kapanır, bir mağaza tatil yapar. Bu boşluklar analizde yanıltır, çünkü eksik gün ile sıfır satış gün aynı şey değildir. pd.date_range(start, end, freq) tam bir takvim üretir. freq için "D" günlük, "B" iş günü, "W" haftalık, "ME" ay sonu gibi kısaltmalar kullanılır. Başlangıç ve bitiş dahildir; periods parametresiyle de yalnızca başlangıç ve adet vererek üretebilirsiniz.

Eksik günleri görmek için reindex kullanılır: df = df.reindex(takvim) komutu takvimdeki her gün için bir satır açar, veri olmayan günlere NaN koyar. Sonra karar sizindir. Satış gibi sayımlarda boş günler gerçekten sıfır satışsa fillna ile sıfır yazmak uygun olur. Sıcaklık ya da fiyat gibi sürekli bir ölçümde ise bir önceki değeri taşımak (ffill) ya da iki ölçüm arasını doğrusal doldurmak (interpolate) daha mantıklıdır. Yanlış doldurma yöntemi seçmek, doğru kodla yanlış sonuç üretmenin en yaygın yoludur.

Bu aşamada kontrol sorusu şudur: veri sıklığı ne olmalı? Günlük bir seriyi iş günü takvimine oturtmak ile saatlik bir seriyi günlük takvime oturtmak farklı kararlardır. Takvimi önce kafanızda tanımlayın, sonra kodlayın.

Resample: günlükten aylığa, saatlikten günlüğe

Zaman serisinde en çok yapılan iş, sıklığı değiştirmektir. resample zamana göre bir groupby gibi çalışır: önce bir sıklık kuralı verirsiniz, ardından bir özet fonksiyonu uygularsınız. df["tutar"].resample("ME").sum() günlük satışları aylık toplama çevirir. Aynı kuralla mean, max, last, count ya da ohlc kullanabilirsiniz.

Hangi özet fonksiyonu seçeceğiniz verinin doğasına bağlıdır. Satış tutarı gibi akış değerlerinde sum, sıcaklık gibi seviye ölçümlerinde mean, hisse fiyatı gibi dönem sonu değerlerinde last doğrudur. Stok gibi bir bakiyeyi toplamak anlamsızdır; dönem sonu bakiyesi için last alınır. Bu ayrımı atlamak raporlarda yanlış rakama yol açar.

Sınır davranışı da önemlidir. Çoğu sıklıkta aralık solda kapalı ve etiket soldadır; ancak ay sonu, yıl sonu, çeyrek sonu ve hafta kuralları için varsayılan sağdır. Bu yüzden haftalık özetin hangi güne etiketlendiğine bakın ve gerekirse closed ile label parametrelerini açıkça verin. Birden fazla sütunu farklı fonksiyonlarla özetlemek için resample ardından agg kullanılır: örneğin tutar için sum, adet için mean. Sonuçta ortaya çıkan aylık tabloyu doğrudan grafiğe verebilir ya da yönetim raporuna aktarabilirsiniz.

Kaydırma, fark ve hareketli ortalama

Zaman serisinden anlam çıkarmanın klasik araçları şunlardır: kaydırma, fark ve pencere. shift() değerleri bir adım kaydırır; böylece her satırın yanına bir önceki dönemin değeri gelir ve değişimi hesaplayabilirsiniz. Önemli ayrıntı: freq vermezseniz değerler kayar, index yerinde kalır ve ilk satır NaN olur; freq verirseniz etiketler kayar.

Dönemler arası değişim için diff() mutlak farkı, pct_change() oransal değişimi verir. Bir mağazanın aylık satış büyümesini görmek istiyorsanız önce resample ile aylığa çevirir, sonra pct_change uygularsınız. Aynı ayı geçen yılın aynı ayıyla kıyaslamak için dönem sayısını yıllık sıklığa göre vermeniz gerekir; mevsimsel işlerde bu, ardışık aylara bakmaktan daha doğru bir yoldur.

Gürültülü bir seriyi okunur hale getirmek için rolling kullanılır. rolling(window=pencere).mean() her noktada son birkaç gözlemin ortalamasını alır ve kısa süreli dalgalanmaları yumuşatır. Pencereyi gözlem sayısı yerine süre olarak da tanımlayabilirsiniz; bu, düzensiz aralıklı veride daha güvenlidir. Pencere ilk satırlarda dolmadığı için baştaki değerler NaN gelir; bunu hata sanmayın, min_periods parametresiyle davranışı ayarlayabilirsiniz. expanding ise başlangıçtan bugüne kümülatif ortalama ve toplam için kullanılır.

Saat dilimleri ve dönem (Period) kavramı

Farklı ülkelerden ya da sistemlerden gelen kayıtlarda saat dilimi hatası sessizce yanlış gün toplamı üretir. Gece yarısına yakın bir işlem, UTC'de bir önceki günde, İstanbul'da bir sonraki günde görünebilir. pandas'ta saat dilimi içermeyen (naive) zamana tz_localize ile bir dilim iliştirirsiniz; dilimli zamanı başka bir dilime çevirmek için tz_convert kullanılır. İki kavramı karıştırmayın: localize "bu saat şu dilimdeydi" der ve değeri değiştirmez, convert ise aynı anı başka bir saat diliminde gösterir.

Pratik kural şudur: sistemler arası veriyi önce UTC olarak saklayın, raporlamada yerel dilime çevirin. Günlük toplam çıkarmadan önce de yerel dilime çevirmek gerekir, aksi halde gün sınırı kayar.

Period ise bir an değil bir zaman aralığını temsil eder. pd.Period("yıl-ay") bir ayı, pd.period_range ise ardışık dönemleri verir. Muhasebe dönemleri, çeyrekler, mali yıllar gibi "an" değil "aralık" olan kavramlarda Period ve to_period tercih edilir. Tarih damgası (Timestamp) ile dönem arasındaki fark, aylık raporlarda ay sonu damgası ile ayın tamamını karıştırmamayı sağlar.

Sık yapılan hatalar ve bir kontrol listesi

Zaman serisi kodunda tekrar eden hatalar şunlardır: • Tarih sütununu metin olarak bırakmak ve sıralamayı alfabetik yapmak. • Gün-ay sırasını belirtmeden okuyup ayları ters çevirmek. • Index'i sıralamadan dilimleme ya da resample yapmak. • Eksik günleri görmeden ortalama almak; boş günleri sıfır saymak ya da tam tersi. • Stok gibi bakiye değerlerini toplamak. • Saat dilimi dönüşümü yapmadan günlük toplam çıkarmak. • Rolling pencerenin ilk satırlarındaki NaN değerleri gizlemek ya da yanlış yorumlamak.

Bir çalışmayı bitirmeden önce kısa bir kontrol listesi işe yarar: sütun datetime64 mi, NaT var mı, index sıralı ve tekrar eden tarih içeriyor mu, sıklık beklediğiniz gibi mi (df.index.is_monotonic_increasing, df.index.duplicated().any()), eksik dönemler bilinçli mi dolduruldu, resample fonksiyonu veri türüne uygun mu. Her adımı bir hücrede gösterip kendi çıktınızı doğrulamak, başkasına verdiğiniz analizin güvenilirliğini belirler.

Öğrenme sırası olarak önce to_datetime ve index işlemlerini, sonra resample ve shift'i, en son saat dilimi ile rolling'i çalışın. Kendi iş verinizle, örneğin bir aylık satış dökümüyle, her adımı tekrarlamak okumaktan daha hızlı öğretir.

Bu beceriyi Mindset programlarında nerede çalışırsınız

Python ile Veri Analizi (Pandas) eğitimi, tarihli veriyle çalışan raporlama ve analiz ekipleri için uygundur: finans, satış operasyonu, planlama ya da müşteri analitiği alanında tablo hazırlayan çalışanlar aynı kodu her ay elle yinelemek yerine tekrar çalıştırılabilir akışa çevirmeyi hedefler. Programın modül başlıkları arasında veri temizleme ve ön işleme, gruplama ve toplulaştırma, veri birleştirme ile iş analitiğinde vaka çalışmaları yer alır; tarih sütunlarının temizlenmesi ve dönemsel özetlerin çıkarılması bu akışın doğal parçasıdır. Kurumsal ekipler için, ortak bir veri setinde herkesin aynı dönem tanımını kullanması gibi pratik bir fayda sağlar.

İlgili Mindset programı

Python ile Veri Analizi (Pandas)

Sık sorulanlar

Sık sorulan sorular

Pandas'ta metin tarih sütunu datetime'a nasıl çevrilir?

pd.to_datetime fonksiyonunu kullanırsınız. Türkçe dosyalarda gün.ay.yıl biçimi yaygın olduğundan format="%d.%m.%Y" ile biçimi açıkça verin ya da dayfirst=True kullanın. Bozuk hücreler varsa errors="coerce" ile bunları NaT yapıp sonra inceleyin. Sonucu aynı sütuna geri yazmayı unutmayın, aksi halde sütun metin olarak kalır.

resample ile groupby arasındaki fark nedir?

groupby herhangi bir sütun değerine göre gruplar. resample yalnızca zaman index'i üzerinde çalışır ve sıklığı değiştirir; eksik dönemleri de otomatik gösterir. Aylık toplam gibi zamana bağlı özetlerde resample daha kısadır ve takvime duyarlıdır. Zaman dışı bir kritere göre özetliyorsanız groupby kullanın.

NaT ne demek ve nasıl temizlenir?

NaT, tarih sütunlarında eksik değerin karşılığıdır, yani sayısal veriyi ilgilendiren NaN'in tarih halidir. Çözümlenemeyen hücreler coerce ile NaT olur. isna() ile satırları listeleyip kaynak veriyi düzeltebilir, dropna ile atabilir ya da başka bir sütundan türetilebiliyorsa doldurabilirsiniz. Önce nedenini anlamak, doğrudan silmekten daha güvenlidir.

Hareketli ortalama ne işe yarar?

Rolling ortalama, gürültülü bir serinin kısa dalgalanmalarını yumuşatır ve eğilimi daha belirgin gösterir. Günlük satışlardaki hafta içi hafta sonu salınımını silip genel yönü görmek bunun tipik örneğidir. Pencere genişledikçe seri daha pürüzsüz, ama gecikmeli olur; pencereyi veri sıklığına ve karar ufkuna göre seçin.

Saat dilimi neden önemlidir, ne zaman localize ne zaman convert kullanılır?

Gece yarısına yakın kayıtlar saat dilimine göre farklı güne düşer ve günlük toplamları kaydırır. Saat dilimi olmayan zamana dilim iliştirmek için tz_localize, dilimli zamanı başka dilimde göstermek için tz_convert kullanılır. Genel uygulama, depolamada UTC tutmak ve raporlamadan önce yerel dilime çevirmektir.

Pandas ile Tarih ve Zaman Serisi İşleme Rehberi