Zaman Serileri Analizi 2 Ek: Zaman Serilerinin Görselleştirilmesi

Zaman serileri
Author

Murat Öztürkmen

Published

December 17, 2021

Ek 2: Zaman Serilerinin Görselleştirilmesi

Bir zaman serisinin analizine başlamadan önce, serinin geldiği alanın bilmenin yanında, serinin nasıl göründüğünü bilmek, bize birçok ipucu sağlar. Bu ek yazıda, zaman serilerini görselleştirmek için yararlı olabilecek bazı Python çerçevelerini göreceğiz. İlerleyen yazılarda bunlar oldukça işimize yarayacak ve hatta burda giriş yaptığımız düzeyin de ötesine geçmeye çalışacağız.

Bu yazıda görselleştirmek için üç veri üzerinde çalışacağız: Türkiye için 1960-2020 dönemine ait logaritmik dönüşümü yapılmış yıllık GSYH verisi, İstanbul için 2015-01:2021-11 dönemi aylık trafik endeksi ve son 5 yıllık döneme ait günlük Vestel hisse senedi verileri. Bu verileri çalışma ortamına alalım:

# gereksiz uyarıları gizlemek için
import warnings
warnings.filterwarnings("ignore")

# gsyh verisinin çalışma ortamına alınıp düzenlenmesi
from pandas_datareader import wb
import numpy as np
import pandas as pd

gsyh = wb.download(indicator='NY.GDP.PCAP.KD', country=['TR'], start=1960, end=2020).reset_index()
gsyh = gsyh.rename(columns={'NY.GDP.PCAP.KD':"gsyh"})
gsyh['log_gsyh'] = np.log(gsyh['gsyh'])
gsyh = gsyh.sort_values(by="year")

print(gsyh.head())
   country  year         gsyh  log_gsyh
60  Turkey  1960  2509.623463  7.827888
59  Turkey  1961  2477.795384  7.815124
58  Turkey  1962  2553.614058  7.845265
57  Turkey  1963  2719.253349  7.908113
56  Turkey  1964  2800.103587  7.937412
import requests

# trafik indeksi verisini içeri almak için
def trafik_indeksini_al(periyot=1, frekans='D'):
    
    """
    Trafik indeksi veri çerçevesini döndürür.
    
    Args:
        peryot (int): periyot sayısı.
        frekans (str): zaman frekansı. Y:year, M:month, D:day, H:hour, 5M:5 minutes. default:D
    
    Returns:
        veri (pandas.DataFrame): trafik indeksi veri çerçevesi
    """
    
    # url
    url = "https://api.ibb.gov.tr/tkmservices/api/TrafficData/v1/TrafficIndexHistory/" + str(periyot) + "/" + frekans
    
    # api adresinden verinin alınması
    istenen_veri = requests.get(url)
    
    # verinin json biçimine dönüştürülmesi
    istenen_veri_json = istenen_veri.json()
    
    # istenen verinin pandas.DataFrame biçimine dönüştürülmesi
    veri = pd.DataFrame.from_dict(istenen_veri_json)
    
    return veri

trafik_indeksi = trafik_indeksini_al(periyot=3600, frekans='M')

print(trafik_indeksi.head())
   TrafficIndex     TrafficIndexDate
0            32  2015-12-01T00:00:00
1            29  2015-11-01T00:00:00
2            30  2015-10-01T00:00:00
3            29  2015-09-01T00:00:00
4            32  2015-08-01T00:00:00
# yfinance çerçevesinin çalışma ortamına alınması
import yfinance as yf

vestel = yf.Ticker("VESTL.IS")
vestel_fiyatlar = vestel.history(start="2016-01-01", end="2021-06-01")

print(vestel_fiyatlar.head())
                Open      High       Low     Close    Volume  Dividends  \
Date                                                                      
2015-12-31  4.071194  4.110567  3.992447  4.023946   4774222          0   
2016-01-01  4.023946  4.023946  4.023946  4.023946         0          0   
2016-01-04  3.897951  3.953074  3.850703  3.905826   4890882          0   
2016-01-05  3.945199  3.984572  3.850703  3.937325   8040998          0   
2016-01-06  3.921575  4.016071  3.913700  4.000321  12378165          0   

            Stock Splits  
Date                      
2015-12-31             0  
2016-01-01             0  
2016-01-04             0  
2016-01-05             0  
2016-01-06             0  

E.2.1. pandas, matplotlib ve seaborn ile Görselleştirme

DataFrame yapısındaki bir zaman serisini, hızlıca görselleştirmenin en kestirme yolu, pandas metodlarını kullanmaktır:

gsyh.plot(x="year", y="log_gsyh", figsize=(15,8));

İkinci kolay yol, matplotlib veya seaborn metodlarını kullanmaktır:

# matplotlib ve seaborn çerçevelerinin çağırılması
import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(15, 8))
plt.grid(True)
plt.plot(gsyh.year, gsyh.log_gsyh, label='gsyh', color='r')
plt.xticks(rotation=90)
plt.legend(loc=2)
plt.show()

Benzer bir çizimi seaborn ile de yapabiliriz:

plt.figure(figsize=(15, 8))
sns.lineplot(x="year", y="log_gsyh", legend="auto", data=gsyh)
plt.grid()
plt.xticks(rotation=90)
plt.title("Türkiye İçin GSYH (log) ")
plt.show()

Son iki çizimde, ızgara (grid) özelliklerini de ekledik. Son çizimde grafiğe başlık ekledik. Seyrek gözlemli zaman serilerini çizerken, ızgara gibi işaretleyici (marker) eklemek de çizimi okumayı ve yorumlamayı kolaylaştırabilir. Yukarıdaki çizim için bunu marker="o" argümanı ekleyerek yapalım:

sns.set_style("darkgrid")

plt.figure(figsize=(15, 8))
sns.lineplot(x="year", y="log_gsyh", marker="o", data=gsyh)
plt.xticks(rotation=90)
plt.title("Türkiye İçin GSYH (log) ")
plt.show()

Zaman serilerini çizerken, yıllık bazda trendi, aylık/haftalık bazda da mevsimselliği görmek için kutu çizimleri (box plot) yararlı olabilir. Trafik indeksi verisi için ay ve yıl değişkenlerini oluşturup yıllık ve aylık bazda kutu çizimlerini yapalım:

# zaman değişkenini `object` veri tipinden `DateTime` veri tipine dönüştürelim
trafik_indeksi['TrafficIndexDate'] = pd.to_datetime(trafik_indeksi["TrafficIndexDate"])
# ay değişkeni oluşturalım
trafik_indeksi["ay"] = trafik_indeksi['TrafficIndexDate'].dt.month
# yıl değişkeni
trafik_indeksi["yıl"] = trafik_indeksi['TrafficIndexDate'].dt.year

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15, 8))

sns.boxplot(trafik_indeksi['yıl'], trafik_indeksi['TrafficIndex'], ax=ax[0])
ax[0].set_title('Yıl Bazında Kutu Çizimi\n(Trend)', fontsize = 20, loc='center', fontdict=dict(weight='bold'))
ax[0].set_xlabel('Yıl', fontsize = 16, fontdict=dict(weight='bold'))
ax[0].set_ylabel('Trafik İndeksi', fontsize = 16, fontdict=dict(weight='bold'));

sns.boxplot(trafik_indeksi['ay'], trafik_indeksi['TrafficIndex'], ax=ax[1])
ax[1].set_title('Ay Bazında Kutu Çizimi\n(Mevsimsellik)', fontsize = 20, loc='center', fontdict=dict(weight='bold'))
ax[1].set_xlabel('Ay', fontsize = 16, fontdict=dict(weight='bold'))
ax[1].set_ylabel('Trafik İndeksi', fontsize = 16, fontdict=dict(weight='bold'));

Mevsimselliğin çizilmesiyle eğer varsa mevsimsellik daha net görülebilir, önemli değişimler daha net görülebilir. Trendin çizilmesiyle, yıl ve ay bazında önemli değişimler ve uç durumlar daha açık olarak görülebilir.

E.2.2. Etkileşimli Görselleştirme-1: plotly ve plotly-express

Gerek zaman serilerinde gerekse de farklı veri tiplerinde olsun, özellikler web bazlı grafik çıktılarında etkileşimli çizimler, sunum ve veri inceleme açısından statik çizimlere göre birtakım faydalar sunarlar.

İlk olarak plotly ve plotly-express çerçeveleri ile zaman serileri görselleştirmesini yapacağız. Çerçeveyi, bilgisayarınıza indirmek oldukça kolaydır:

pip install plotly

BİST100 kapanış (Close) fiyatlarını plotly ile görselleştirelim:

# plotly çerçevesininden `graph_objects` modülünü içeri alalım
import plotly.graph_objects as go

fig = go.Figure()
fig.add_trace(
    go.Scatter(x=vestel_fiyatlar.index, y=vestel_fiyatlar.Close)
)
fig.show()

Yukarıda çizdiğimiz grafik için, çok daha hızlı ve pratik bir yol, plotly-express modülüdür:

# plotly-express modülünü içeri alalım
import plotly.express as px

fig = px.line(vestel_fiyatlar, x = vestel_fiyatlar.index, y = vestel_fiyatlar.Close)
fig.show()

E.2.3. Etkileşimli Görselleştirme-2: bokeh ve holoviews

Python ile, etkileşimli çizimler yapmak için geliştirilmiş bir başka çerçeve de bokeh dir. bokeh üzerine geliştirilmiş bir üst seviye çerçeve de holoviews dir. Aslında holoviews, sadece bokeh ile değil, arkaplanda matplotlib, plotly, vega gibi farklı çerçeveler ile birlikte çalışabilen bir arayüz gibidir.

Her iki çerçeveyi de çalışma ortamına eklemek oldukça kolaydır:

pip install bokeh
pip install "holoviews[recommended]" 

İlk olarak bokeh ile çizim yapalım. Bunun için, eğer jupyter notebook gibi bir ortamda çalışıyorsanız, bu ortamda çizimi göstermek için output_notebook() metodunu kullanmanız gerekir.

# bokeh çerçevesinden gerekli modüllerin çağırılması
from bokeh.plotting import figure
from bokeh.io import push_notebook, show, output_notebook
from bokeh.models import ColumnDataSource
output_notebook()

kaynak = vestel_fiyatlar[['Close']]
p = figure(x_axis_type="datetime", plot_width=800, plot_height=350)
p.line("Date", "Close", source=kaynak)
show(p, notebook_handle=True);
Loading BokehJS ...

holoviews ile benzer çizimi elde etmek, nispeten daha kolaydır

# gerekli modüllerin çağırılması
import holoviews as hv
from bokeh.io import output_notebook
hv.extension('bokeh')
output_notebook()
Loading BokehJS ...
hv.Curve(vestel_fiyatlar, ('Date', 'Tarih'), ('Close', 'Fiyat'), label="VESTL").opts(width=700, height = 400, show_grid=True)