Grafik Çizimi
Emre S. Tasci emre.tasci@hacettepe.edu.tr
Verilerin grafiksel olarak temsili, bizlere elimizdeki bilgilerin birbirleriyle ilişkileri ve birbirlerine bağlı olarak gelişimleri hakkında bilgi verdiği gibi, arkalarında yatan model ve formülleri de görebilme imkanı sunar. Bunlara ilaveten, grafiklere bakarak, elimizdeki aralıkta ölçümünü yapmadığımız noktalara karşılık gelen değerleri ve dahi aralığın dışındaki yerleri de tahmin edebiliriz: ilk işleme içdeğer bulma ("interpolation"); ikinci işleme ise öteleme ("extrapolation") denir.
Grafik çizebilmek için, öncelikle, tabii ki, elimizde veriler olması gerekmekte... 8)
Bu dersimizde kullanacağımız veriler, Horvat & Jecmenica'nın "The free fall experiment" (Resonance 21, 259-275 (2016) | DOI: 10.1007/s12045-016-0321-9) makalesinden alınmıştır.
Elimizde, sınıf ortamında, yerden farklı yüksekliklerden bırakılan bir kütlenin düşme sürelerinin ölçüm verileri var:
Yükseklik (m) | Düşüş Süresi (s) |
---|---|
0.2 | 0.201900 |
0.7 | 0.377759 |
0.8 | 0.403882 |
1.2 | 0.494707 |
1.3 | 0.514983 |
1.8 | 0.606071 |
İlk iş olarak verileri veriler
diye bir matrise girip, saklayalım:
veriler = [0.2 0.201900
0.7 0.377759
0.8 0.403882
1.2 0.494707
1.3 0.514983
1.8 0.606071] # yukseklik (m) | zaman (s)
işlemek kolay olsun diye, 1. sütundaki verilere y
, 2. sütundakilere de t
diyelim:
y = veriler(:,1)
t = veriler(:,2)
Bir deney yaparken, "kontrol parametresi" dediğimiz, değerini bizim belirleyip, ona göre ölçümler aldığımız parametreyi grafikte yatay eksene (x-ekseni) yerleştiririz, kontrol parametresinin farklı değerlerinde ölçtüğümüz değerleri de düşey eksene (y-ekseni) işaretleriz.
Verileri aldığımız serbest düşüş deneyinde, kontrol parametresi yükseklik olduğundan, onu yatay eksene, ölçülen parametre olan süre değerlerini ise düşey eksende işaretleyeceğiz.
Octave'da grafik çizdirmek çok pratiktir (hatta o kadar pratiktir ki, Python'a bile neredeyse doğrudan aktarılmıştır (matplotlib modülü altında)). Grafik çizdirmek için kullandığımız komut, İngilizce'de grafik çizmek anlamına gelen plot()
komutudur. plot()
fonksiyonuna girilen birinci parametre yatay eksen değerlerini, ikinci parametre ise düşey eksen değerlerini ifade eder.
Elimizdeki verileri en basit şekilde plot(y,t)
diyerek çizdiririz:
plot(y,t)
Tebrikler! İlk grafiğinizi çizdiniz. Fakat pek de güzel (/düzgün) görünmüyor gibi sanki. Aslında biraz dikkat bakınca, tablodaki verilerin grafikteki doğruların kırıldıkları noktalar olduğunu görebiliyoruz gibi (gibi)... Tabloyu aşağıya tekrardan alıntılayalım, bir bakın bakalım, siz de kırılma noktalarının oralara geldiğini teyit edebilecek misiniz?
Yükseklik (m) | Düşüş Süresi (s) |
---|---|
0.2 | 0.201900 |
0.7 | 0.377759 |
0.8 | 0.403882 |
1.2 | 0.494707 |
1.3 | 0.514983 |
1.8 | 0.606071 |
Böyle zor oluyor hakikaten... Onun yerine, verileri grafik üzerinde göstersek?
plot(y,t,"o")
Bence bu şekilde çok daha açık oldu. Fark ettiyseniz, bunu, plot
fonksiyonuna 3. bir parametre ("o"
) vererek hallettik. Buna biçim parametresi diyoruz ve tırnak içinde belirtiyoruz. o
dediğimiz için, veri noktalarını temsil eden işaretçikleri ("markörleri") daireler şeklinde gösterdi.
Dilersek başka bir sürü şekil markör kullanabiliriz:
Sembol | İşaret |
---|---|
+ | Artı |
o | Daire |
* | Yıldız |
. | Nokta |
x | Çarpı |
s | Kare (square) |
d | Paralelkenar/Elmas (diamond) |
^ | Sivri ucu yukarıda olan üçgen |
v | Sivri ucu aşağıda olan üçgen |
> | Sivri ucu sağda olan üçgen |
< | Sivri ucu solda olan üçgen |
p | 5 köşeli yıldız (pentagram) |
h | 6 köşeli yıldız (hexagram) |
# Verileri karelerle temsil edelim:
plot(y,t,"s")
Grafiğin biçim parametresinde başka özellikler de tanımlayabiliriz, örneğin rengi.
Renkleri hazır tanımlı renkler arasından belirtebiliriz (dilersek 'color' parametresi ile herhangi bir RGB üçlüsü olarak da belirtebiliriz, ama bu aşamada çok gerekli değil).
Hazır tanımlı renklerin listesine gelirsek:
Sembol | Renk |
---|---|
k | Siyah (blacK) |
r | Kırmızı (Red) |
g | Yeşil (Green) |
b | Mavi (Blue) |
m | Mor (Magenta) |
c | Turkuaz (Cyan) |
w | Beyaz (White) |
Bu renk sembollerini de doğrudan markör sembolünün yanına yazıyoruz - çakışma olmadığı için hangisini önce yazdığımızın bir önemi yok, yeter ki aynı tırnak işaretinin içerisinde olsunlar: örneğin "xr"
de, "rx"
de, bize kırmızı çarpılı markörler çıkartır:
# Kırmızı çarpılar
plot(y,t,"rx")
Çarpılar biraz küçük gibi görünüyor, büyütme işini "markersize"
(markör boyu) parametresi ile yapıyoruz. Bu parametre markör şekli ve renginden biraz farklı bir şekilde tanımlanıyor yalnız: önce parametreyi, ardından değeri giriyoruz şu şekilde:
# Kırmızı büyük çarpılar
plot(y,t,"rx","markersize",10)
Eğer daire, kare veya yıldız gibi içi olan bir markör kullanıyorsak, içinin ve kontürünün renklerini sırasıyla "markerfacecolor"
ve "markeredgecolor"
parametreleriyle ayrı ayrı belirleyebiliriz.
Örneğin, içi yeşil, dışı kırmızı daireler kullanalım:
plot(y,t,"o","markersize",10,"markerfacecolor","g","markeredgecolor","r")
Octave'da uzun satırları bölmek için ...
operatörü kullanılır. Yukarıdaki uzun komutu, iki satıra bölmek isteseydik:
plot(y,t,"o","markersize",10,...
"markerfacecolor","g","markeredgecolor","r")
şeklinde yazabilirdik (boşluklar önemli olmadığından, alt satırlara geçtiğimizde yazmaya başlamadan önce istediğimiz kadar boşluk bırakabiliriz). Bu taktiği çok fazla elemanı olan dizileri yazmak için de kullanabiliriz:
cok_elemanli_dizi = [123,321,123,321,432,543,...
213,12,34,65,834,23,543,234,2343,4234,432,...
23423,432423,42342,342,432423,432,234,324]
Markörleri iyice kavradığımıza göre, grafiklerimize biraz daha çeşitlilik katalım. Veri noktalarımızı çizgi ile birleştirmek için, biçim kısmına en temel halde bir -
sembolü ekleriz:
plot(y,t,"o-")
Biçimde iki paremetre belirledik, "o" ile "-": ilki veri noktalarını daireler ile temsil edilmesini, ikincisi de bu veri noktalarının düz çizgi ile birleştirilmesini belirtmekte (hatırlarsanız, ilk çizdirdiğimiz grafikte (plot(y,t)
) veri noktaları ayrıca gösterilmemiş, sadece doğrudan çizgilerle araları birleştirilmişti).
Her şeye olduğu gibi, çizgi biçimlerine de müdahale edebiliyoruz: çizgilerimizin çeşitlerini (düz, kesikli, nokta nokta, çizgi-nokta); rengini, kalınlığını, onlara karşılık gelen anahtar kelime / sembollerle ayarlayabiliriz.
Yukarıda da yazdığımız üzere, 4 farklı çeşit çizgi ile çalışabiliriz:
Sembol | Çizgi çeşidi |
---|---|
- | Düz çizgi |
-- | Kesikli çizgi |
: | Nokta nokta |
-. | Çizgi-nokta |
Nasıl göründüklerini altta topluca inceleyebilirsiniz (o 2x2 grafiği nasıl çizdirdiğimizi (subplot) de birazdan göreceğiz ;) :
subplot(2,2,1)
plot(y,t,"o-")
title("Duz Cizgi")
subplot(2,2,2)
plot(y,t,"o--")
title("Kesikli Cizgi")
subplot(2,2,3)
plot(y,t,"o:")
title("Nokta nokta")
subplot(2,2,4)
plot(y,t,"o-.")
title("Cizgi-nokta")
Aslında en başından beri grafikleri çizerken, normal renk parametresi (örn. "or"'deki "r") olarak belirttiğimiz renk, temel olarak çizgi rengidir, markörlerin rengi de ("markerfacecolor" ve/veya "markeredgecolor" ile) aksi belirtilmedikçe bu renkte çizilir.
Yani, grafiğimizi mavi kesikli çizgi üzerine dışı kırmızı, içi yeşil dairesel markörlerle çizdirmek istersek, bunu şu şekilde yaparız:
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r")
Çizgi kalınlığını da linewidth
parametresi ile belirtiriz. Yukarıdaki grafiği daha kalın çizgilerle çizmek için:
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4)
Markörler çizgilerin yanında biraz küçük kaldı, onları da coşturup, bu konuyu kapatalım:
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
Grafiklerimiz bu şekilde matematiksel olarak grafik olsalar da, fiziksel açıdan pek de işe yarar şeyler değiller: Neyin grafiği bu? Yatay ve düşey eksenler neyi temsil ediyor, birimleri nedir? Veri noktaları tam olarak neye karşılık geliyor? Bu noktada devreye grafik tanımlayıcıları girer.
Eksenlerin tanımlarını xlabel()
ve ylabel()
fonksiyonları ile ve grafiği plot
ile çizdirdikten sonra belirtiriz. title()
fonksiyonu ile de grafiğimizin başlığını yazarız. Örneğimiz üzerinde çalışalım, çok daha anlaşılır olacak:
# Grafiğimizi çizdiriyoruz
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
# Tanımlamaları yapıyoruz
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
Grafik üzerindeki verilerimizin değerleri rahatça anlaşılıp, kıyaslanabilsin diye, eksenleri böldüğümüz aralıklardan çizgiler uzatırız. Bu kontrolü grid
komutu ile gerçekleştiriyoruz:
grid on
bu çizgilerin görüntülenmesini açargrid off
da kaparEksenler üzerindeki hangi değerlerin hangi aralıklarla (örneğin yukarıdaki grafikte yatay eksen 0'dan 2'ye 0.5'lik aralıklarla; düşey eksen ise 0.2'den 0.7'ye 0.1'lik aralıklarla bölünmüş durumda) bölüneceğini, ya da bir başka deyişle çentik konumlarını ise sırasıyla xticks()
ve yticks()
fonksiyonları ile belirtiriz.
Yukarıdaki örnek üzerinde çalışmaya devam edersek, önce ızgarayı (grid'i) açalım:
# Grafiğimizi çizdiriyoruz
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
# Tanımlamaları yapıyoruz
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
# Izgarayı açalım
grid on
sonrasında da yatay ve düşey eksendeki çentikleri (ticks) sıklaştıralım:
# Grafiğimizi çizdiriyoruz
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
# Tanımlamaları yapıyoruz
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
# Izgarayı açalım
grid on
# Çentikleri yeniden tanımlayalım
xticks(0:0.1:2)
yticks(0.2:0.05:0.7)
Grafik aynı grafik olsa da, okunabilirliği epey artmış oldu. Çentik tanımlamasını yaparken, geçen dersimizde tanıştığımız aralık operatörünü (başlangıç:adım uzunluğu:bitiş) kullandığımıza dikkatinizi çekerim.
Pek sık karşılaşılmasa da, çentikleri dilerseniz kafanıza göre, eşit olmayan aralıklarla da tanımlayabilirsiniz:
# Grafiğimizi çizdiriyoruz
plot(y,t,"b--o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
# Tanımlamaları yapıyoruz
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
# Izgarayı açalım
grid on
# Çentikleri yeniden tanımlayalım
# Yatay eksendekiler için sadece veri noktalarını
xticks([0.2, 0.7, 0.8, 1.2, 1.3, 1.8])
# Düşey eksendekiler içinse kafamıza göre alalım...
yticks([0.23,1/3,0.65])
(tahmin edebileceğiniz üzere, yatay eksendeki çentikleri tek tek yazmak yerine, doğrudan xticks(y)
de diyebilirdik - ne de olsa y
değişkeni doğal olarak yukarıda girdiğimiz veri noktalarını tutmakta ;)
Grafiğimizin çizim sınırlarını axis()
fonksiyonu ile belirliyoruz. Parametre olarak bir dizi alır ve dizinin eleman sayısı 2 ise bunlar yatay eksenin minimum ve maksimum değerlerini; 4 elemanlı bir dizi ise o zaman da dizinin elemanlarını sırasıyla yatay eksenin minimum ve maksimum değerleri ve düşey eksenin minimum ve maksimum değerleri olarak yorumlar.
Yukarıdaki örneğimizi önce bir düzgün çizdirelim:
# Grafiğimizi çizdiriyoruz
plot(y,t,"b-o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
# Tanımlamaları yapıyoruz
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
# Izgarayı açalım
grid on
Yatay eksenin gösterim aralığını [-1,3], düşey eksen aralığını ise [0,1] yapalım:
# Grafiğimizi çizdiriyoruz
plot(y,t,"b-o","markerfacecolor","g","markeredgecolor","r",...
"linewidth",4,"markersize",30)
# Tanımlamaları yapıyoruz
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
# Izgarayı açalım
grid on
axis([-1,3,0,1])
veriler
Bu serbest düşüş deneyini ellerinde kronometre olmadığından, süreyi saatin saniye kısmıyla ölçen ikinci bir grubun da yapmış olduğunu ve şu sonuçarı aldığını varsayalım:
veriler_2 = [0.20000 0.3
0.70000 0.4
0.80000 0.4
1.20000 0.5
1.30000 0.6
1.80000 0.7]
# 2. sütunu t_2 değişkenine atayalım
t_2 = veriler_2(:,2)
# (y değerleri (1.sütun) ilk veri setiyle
# aynı olduğundan, onu ayrıca bir y_2 değişkenine
# atamadık)
Normalde, ikisini ayrı ayrı çizdirecek olsak:
plot(y,t,"^-b") # 1. grafik
plot(y,t_2,"o-r") # 2. grafik
Şeklinde yazardık. Aynı grafik üzerinde ikisini birlikte çizdirmek içinse tek bir plot()
fonksiyonunda birleştiriyoruz (birleştirirken aralarına virgül koyuyoruz):
# plot(y,t,"^-b") ve plot(y,t,"o-r") yerine:
plot(y,t,"^-b",y,t_2,"o-r")
Hangisinin hangisi olduğunun açıklamasını ise legend()
komutu ile belirtebiliriz (hazır yapıyorken, tanımları da koyalım):
plot(y,t,"^-b",y,t_2,"o-r")
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
legend("Hassas Olcum (1. Grup)","Kaba Olcum (2. Grup)")
# Izgarayı açalım
grid on
Yukarıdaki grafikte gördüğünüz üzere, açıklama kutusu verilerle çakıştı. Bu tür durumlarda kutuyu 8 uç yöne taşımak için "location"
parametresini devreye sokabiliriz. Parametre değerleri olarak 8 temel yönün İngilizce karşılıkları ("north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest") kullanılır. Örneğimizdeki kutucuğu sol-üste, yani "kuzeybatı"ya taşıyalım:
plot(y,t,"^-b",y,t_2,"o-r")
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
legend("Hassas Olcum (1. Grup)","Kaba Olcum (2. Grup)",...
"location","northwest")
# Izgarayı açalım
grid on
Kutucuğu tümden grafiğin dışına almak içinse location
parametresinin değerine dışarı anlamına gelen outside
terimini yamarız:
plot(y,t,"^-b",y,t_2,"o-r")
xlabel("Yukseklik (m)")
ylabel("Dusus suresi (s)")
title("Serbest Dusus Deneyi")
legend("Hassas Olcum (1. Grup)","Kaba Olcum (2. Grup)",...
"location","northwestoutside")
# Izgarayı açalım
grid on
legend
parametresi ile başka birçok şey daha yapmak mümkün, detaylar için ilgili komutun açıklama sayfasına göz atabilirsiniz.
Octave, temel olarak sembolik bir dil olmadığı için, fonksiyon çizdirirken de fonksiyonun belli yerlerdeki değerlerinden bir veri dizisi oluşturup, onların grafiğini çizdiririz.
Örneğin $y = x^2$ grafiğini $x\in[0,1]$ aralığı için çizdirelim.
x = 0:0.2:1
y = x.**2
(üs alma operatöründen önce "." sembolünü koyarak, x vektörünün karesini değil, eleman bazında kare alma işlemini gerçekleştirdiğimizi belirttik - aman dikkat!)
Grafiğimizi artık çizdirebiliriz:
plot(x,y,"-")
Pek kesik kesik görünüyor. Bunun sebebi ele aldığımız değer adedi. 6 parça ([0, 0.2, 0.4, 0.6, 0.8, 1]) ile ancak bu kadar oluyor. Arttıralım bakalım, neye benzeyecek...
x = 0:0.1:1;
y = x.**2;
plot(x,y)
Epey düzelme var. peki aralığı 125 çentiğe ayırmak istesek? Aralık operatörü ile bunu yapmak mümkün ama oturup adım uzunluğunu hesaplamak gerekecek. Bu tür durumlarda ise yardımımıza, aralık operatörünün kardeşi linspace()
fonksiyonu yetişiyor. linspace
ile başlangıç ve bitiş değerlerini verip, kaç çentik istediğimizi bildiriyoruz, o da eşit aralıklara bölüp, bize çentikleri döndürüyor.
Örneğin: 0 ile 1 arasını 3 çentikle bölelim:
linspace(0,1,3)
Grafiğimizi bu sefer 125 çentikle çizelim:
x = linspace(0,1,125);
y = x.**2;
plot(x,y)
Aynı grafik üzerinde $y_1 = x$ ve $y_2 = x^2$ grafiklerini güzelce çizdirelim:
x = linspace(0,1,125);
y_1 = x;
y_2 = x.**2;
plot(x,y_1,"linewidth",4,x,y_2,"linewidth",4)
legend("y=x","y=x^2","location","southeast")
$y=x$ ve $y=x^2$ fonksiyonlarının grafiklerini $x \in [-10,10]$ aralığında çizdirmeyi deneyelim:
x = linspace(-10,10,250);
y_1 = x;
y_2 = x.**2;
plot(x,y_1,"linewidth",4,x,y_2,"linewidth",4)
legend("y=x","y=x^2","location","southeast")
Bu grafikteki sorun nedir? $x$ 0 ile 1 arasındayken iki grafiğin değerleri gayet güzel anlaşıyorlardı fakat aralık artınca, değerler arasındaki farklar da uçtu gitti, bu nedenle $y_2 = x^2$ fonksiyonu baskın hale gelip, $y_1 =x$ fonksiyonunu gölgeledi. Bu türden, farklı değer aralıklarına sahip fonksiyonları birlikte gösterebilmek için, iki farklı düşey eksen kullanmamızı sağlayan plotyy()
fonksiyonu ile çizim yaparız:
x = linspace(-10,10,250);
y_1 = x;
y_2 = x.**2;
plotyy(x,y_1,x,y_2)
legend("y=x","y=x^2","location","southeast")
Artık grafik çizmeyi epey epey öğrendiğimize göre, aynı grafik tuvali üzerinde farklı grafikleri sıralamayı da görebiliriz. Bu sıralama işini subplot()
komutu ile tanımlıyoruz.
Gözünüzün önüne (2x2)'lik bir matris getirin, örneğin:
$$ \begin{bmatrix}1&2\\3&4\end{bmatrix}$$olsun.
Matrise bir isim vermediğimizden, bir yeri belirtmek için, her seferinde matrisin boyutunu ve yerin indisini belirtiriz. Mesela sağ alt köşedeki elemanı belirtmek için "2'ye 2'lik bir matrisi gözünüzün önüne getirip, onun 4. elemanının yerini düşünün" demek gibi. İşte subplot()
'un parametreleri de bu şekilde çalışıyor. Her birini ayrı ayrı belirtip, oraya ne koyacağımızı tanımlıyoruz sonra. Aşağıdaki örneklere bakarsanız çok daha açıklayıcı olacağını umut ediyorum:
# 1x2'lik bir düzen
subplot(1,2,1)
# 1x2'lik matrisin 1. elemanı, yani soldaki penceredeyiz
plot(x,y_1,"-r")
title("y=x")
subplot(1,2,2)
# şimdi 1x2'lik matrisin 2. elemanı, yani sağ penceredeyiz
plot(x,y_2,"-b")
title("y=x^2")
# 2x1'lik bir düzen
subplot(2,1,1)
# 2x1'lik matrisin 1. elemanı, yani yukarıdaki penceredeyiz
plot(x,y_1,"-r")
title("y=x")
subplot(2,1,2)
# şimdi 1x2'lik matrisin 2. elemanı, yani aşağıdaki penceredeyiz
plot(x,y_2,"-b")
title("y=x^2")
İlle de bütün hücreler dolacak diye bir kural da yok bu arada:
# 2x3'lük bir düzen
subplot(2,3,2)
# 2x3'lik matrisin 2. elemanı, yani yukarı satır, orta sütun
plot(x,y_1,"-r")
title("y=x")
subplot(2,3,3)
# 2x3'lük matrisin 3. elemanı, yani sağ-üst hücre
plot(x,y_1-y_2,"-g")
title("y=x-x^2")
subplot(2,3,4)
# 2x3'lük matrisin 4. elemanı, yani sol-alt hücre
plot(x,y_1+y_2,"-k")
title("y=x+x^2")
subplot(2,3,6)
# şimdi 2x3'lük matrisin 6. elemanı, yani sağ-alt hücre
plot(x,y_2,"-b")
title("y=x^2")
Yukarıdaki örneklerdeki verilerimiz hep sıralı verilerdi, yani noktalarımızı art arda çizgilerle birleştirince anlamlı bir şekil elde ediyor, gelişim sürecini izleyebiliyorduk. Fakat saçılma deneyleri gibi deneylerde (ya da elinizdeki vişne suyu dolu bardağı beyaz halıya düşürdüğünüzde oluşan desenler gibi kazalarda) bu şekilde bir sıralılık aranmaz. Bu tür durumlarda, plot
yerine scatter
fonksiyonunu kullanmak birtakım avantajlar (farklı şekilde büyüklük ve renklendirme yapabilmek gibi) sunar.
Saçılım için genelde çok fazla veriye ihtiyaç duyulur. Vişne bardağımızı kare şeklinde halımızın tam ortasına düşürdüğümüzü ve 300 adet damlanın rastgele yönlere sıçradığını varsayalım.
Rastgele işlemler için rand()
komutunu kullanırız, bize bu haliyle 0 ile 1 (0 dahil, 1 hariç) arasında eşit olasılıkla rastgele bir sayı üretir (düzgün dağılım):
# Hesaplara başlamadan...
rand("seed",219) # Bu şekilde her seferinde aynı "rastgele" sayıların
# çıkmasını sağlıyoruz (yani sizin ürettiğiniz sayıların
# bu ders notundakilerle aynı olmasını)
rand()
rand()
rand(3,5)
# -2 ile 2 arasında rastgele sayılar:
rand(3,5)*4-2
Halımızın merkezini (0,0), boyunu da 4x4 $m^2$ alırsak, üzerine rastgele şekilde dökülen 10 damlanın konumlarını (x,y) cinsinden şu şekilde üretebiliriz:
damlalar = rand(10,2)*4-2
Çizdirmek için scatter
'ı kullanalım:
scatter(damlalar(:,1),damlalar(:,2),500)
Yukarıdaki "500" parametresi boyla orantılı bir değer.
Damla sayısını 300'e çıkaralım:
damlalar = rand(300,2)*4-2;
scatter(damlalar(:,1),damlalar(:,2),500)
Kar beyaz halının ortasına dökülen vişne suyunun damlacıklarının konumu için düzgün dağılım çok da gerçekçi değil bu arada, sonuçta tahmin edebilirsiniz ki, normalde halının merkezine yakın düşen damlacıkların sayısı (/yoğunluğu) halının uçlarına kadar ulaşan damlacık sayısından (/yoğunluğundan) çok daha fazla olacaktır.
Burada "normalde" terimi anahtar kelimemiz. Doğada pek çok kez gözlemlediğimiz, belli bir ortalama değerin etrafında gerçekleşen dağılımlar için "normal dağılım"ı kullanıyoruz (Gauss dağılımı olarak da bilinir), bunu da rand
yerine, randn
fonksiyonunu kullanarak yapıyoruz. (normal dağılımı bütün güzellikleri ve formüler gösterimi ile birlikte "FİZ316 - İstatistik Fizik" dersinizde göreceksiniz 8):
damlalar = randn(1000,2)*4-2;
scatter(damlalar(:,1),damlalar(:,2),500)
(istemeyen okumasın! ;)
scatter
ın plot
dan farkını, renk ve boy çeşitlemeleri yapabilmek olarak belirtmiştik. Her bir veri noktasının boyunu da, rengini de tek tek belirleyebiliriz.
Yukarıdaki örnekte boyu 500 almıştık, onun yerine 1. noktanın boyunu 1, ikincisinin 2, ..., 1000.sininkini 1000 alalım:
scatter(damlalar(:,1),damlalar(:,2),1:1000)
Çok mantıklı bir şey değil ama fikir veriyor. Peki örneğin merkeze ne kadar uzaksa o kadar küçük olsun? Nasıl yaparız?
Önce merkeze olan mesafelerini hesaplarız. Elimizde her bir damlanın x ve y koordinatları olduğuna göre, karelerinin toplamının kökü, ya da daha doğrudan koordinatların norm
u bize mesafeleri verir:
# ilk 10 damlanın koordinatları:
damlalar(1:10,:)
# Kötü yoldan hesaplanmış mesafeler vektörünün ilk 10 elemanı:
mesafeler_kotu = (damlalar(:,1).**2 + damlalar(:,2).**2).**0.5;
mesafeler_kotu(1:10)
# Güzel yoldan hesaplanmış mesafeler vektörünün ilk 10 elemanı:
mesafeler_guzel = norm(damlalar,"rows");
mesafeler_guzel(1:10)
scatter(damlalar(:,1),damlalar(:,2),mesafeler_guzel*100)
Neredeyse olacak gibi -- yukarıdakinde uzaklaştıkça büyüyorlar, halbuki biz uzaklaştıkça küçülmelerini istiyoruz, o halde:
scatter(damlalar(:,1),damlalar(:,2),(1./mesafeler_guzel)*1500)
Renkleri içeriden dışarıya açalım, içlerini de doldularalım...
scatter(damlalar(:,1),damlalar(:,2),...
(1./mesafeler_guzel)*1500,...
mesafeler_guzel,"filled")
Histogram grafikleri dağılımları gösteren türden grafiklerdir. Örneğin, veri olarak geçen senenin (2019-2020 Güz Dönemi) "FİZ219 - Bilgisayar Programlama" dersinin genel sınav notlarını ele alalım:
notlar = [1, 1, 1, 1, 1, 2, 7, 7, 10, 11, 11, 13, 13,...
13.5, 14, 14, 15.5, 17, 18, 20, 21, 21, 22,...
23, 23, 23, 24, 24, 24, 24, 25, 25, 29, 30,...
30, 32.5, 36, 37, 37, 37, 38, 40, 41, 42.5,...
42.5, 43, 46, 46, 53, 59.5, 60, 60.5, 62, ...
63.5, 67, 67, 70, 83, 84, 99];
Toplam 60 kişi sınava girmiş, notların dağılımını görmek için yazmamız gereken komut çok basit:
hist(notlar)
Birazcık daha anlaşılır kılalım:
hist(notlar)
xticks(0:10:100)
yticks(0:20)
title("2019-2020 Guz Donemi FIZ219 Genel Sinav Not Dagilimi")
grid on
Grafiğe bakarak kolayca (0,10] aralığında 9 not olduğunu, (10,20] arasında 11 not olduğunu, vs. görebiliyoruz, ki zaten histogramın amacı da budur.
hist
fonksiyonu varayılan olarak, verileri 10 kutuda toplar. İkinci bir paremetre ile kutu sayısını da belirleyebiliriz:
hist(notlar,20)
xticks(0:5:100)
yticks(0:20)
title("2019-2020 Guz Donemi FIZ219 Genel Sinav Not Dagilimi")
grid on
hist()
fonksiyonu ve parametreleri hakkında daha fazla bilgiyi Octave'ın ilgili kılavuz sayfasında bulabilirsiniz.
Nihayet en süper görünen çizimlere gelebildik! Ama işin kod kısmına geçmeden önce, 3 boyutlu çizimin ne anlama geldiğini tartışalım biraz. 3 boyutlu çizimlerde, $f(x,y,z)$ gibi 3 parametreli fonksiyonların grafikleri çizilmez (o 4 boyutlu bir uzay gerektiriyor maalesef), $f(x,y)$ gibi 2 parametreli fonksiyonların grafikleri çizilir.
Kareli bir kağıt alıp, kesişim noktalarına pozitif veya negatif, çeşitli değerler yazdığınızı düşünün. Sonrasında her noktayı üzerinde yazan değer kadar pozitifse yukarı kaldırdığınızı, negatifse aşağı çektiğinizi varsayın -- işte 3 boyutlu grafik böyle bir şey.
Örneğin, 2x2'lik bir matrisin 9 köşesini aşağıdaki gibi işaretlediğimizi (indislediğimizi) düşünelim:
(Köşelerin koordinatlarını (indislerini) iyice inceleyin, aklınıza yatsın)
Şimdi de, her bir köşenin "z" değerini koordinatlarının karesinin toplamı olarak yazalım. Örneğin (0,-1) noktasının değeri: $0^2+(-1)^2 = 1$ olur. Her köşenin yanına bu değerleri de yazalım:
3 boyutlu grafik çizerken de tam olarak benzer bir süreçten geçiyoruz. Öncelikle, $x=\{-1,0,1\}$ değerleri ile $y=\{-1,0,1\}$ değerlerini harmanlayıp, (-1,-1)'den (1,1)'e olası 9 kombinasyonu üreteceğiz, sonrasında da bu koordinatlara karşılık gelen değer olarak indislerin karelerin toplamını atayacağız.
Önce harmanlama işini yapalım, bunu meshgrid()
fonksiyonu ile gerçekleştiriyoruz:
tx = linspace(-1,1,3)
ty = linspace(-1,1,3)
[xx,yy] = meshgrid(tx,ty)
Biz tx
ile ty
değişkenlerini tanım aralığımız olarak tanımlıyoruz, meshgrid de bunları öyle bir harmanlıyor ki, ürettiği xx
ile yy
üst üste bindirirsek, tam olarak yukarıdaki koordinat sistemi ortaya çıkıyor. 8)
Şimdi de her bir koordinatın değerini koordinatlarının karesi olarak tanımlayalım:
tz = xx.^2 + yy.^2
İyi gidiyoruz, az da kaldı... Şimdi değerleri "1" olan ortaları 1 birim; değerleri "2" olan köşeleri ise 2 birim yukarı kaldırırken, orta noktayı "0" olan değerinden ötürü, masanın seviyesine raptiye ile tutturduğumuzu düşünelim. Görüntüyü kafanızda canlandırabildiniz mi? Şuna benziyor mu?:
mesh(tx,ty,tz)
Elinizi korkak alıştırmayın, tutun ucundan, döndürün, çevirin, ilk üç boyutlu grafiğiniz hayırlı olsun, tadını çıkarın! 8)
Kafamızda rahat canlandırabilelim diye 3x3 = 9 noktada çizdirdik ama tabii ki bu epey kaba bir grafik oldu, biz her eksende 100 nokta alalım (yani ağımız (meshgrid) 100x100 = 10000 köşe olsun):
tx=ty=linspace(-3,3,100);
[xx,yy] = meshgrid(tx,ty);
tz = xx.^2+yy.^2;
mesh(tx,ty,tz)
2 boyutlu grafiklerde yaptığımız gibi, 2 boyutlu grafiklerde de açıklayıcı bilgiler girebiliriz:
mesh(tx,ty,tz);
xlabel ("x");
ylabel ("y");
zlabel ("z");
title ("x^2");
Ya da dilersek, 3 boyutlu çizimin altına iki boyuttaki izdüşümü olan kontür haritasını da ekleyebiliriz. Bunun için mesh
fonksiyonunu değil de meshc
fonksiyonunu kullanıyoruz:
meshc(tx,ty,tz);
sadece kontür haritasını çizdirmek içinse contour()
fonksiyonu var:
contour(tx,ty,tz)
3-boyutlu grafikte dikkat ederseniz sadece tel var, yani ağların arası açık gibi. Ağ yerine yüzey varmış da, onu bükmüşüz gibi olsun istersek surf()
fonksiyonu devreye giriyor:
surf(tx,ty,tz);
surf
'ün de mesh
gibi, kontür haritalı versiyonu var: surfc()
:
surfc(tx,ty,tz);
Aktif grafiği bir dosyaya aktarmak için, print
komutunu kullanırız:
print -d{biçim} {dosya_adı}
şeklinde. Biçim, png olur, pdf, jpg, gif, ps, eps...; dosya adı size kalmış ama uyumluluk açısından boşluksuz, Türkçe karakter olmasını tavsiye ederim.
surfc(tx,ty,tz);
print -dpng "3D_Grafik.png"
Grafiğimizi yukarıdaki komutla "3D_Grafik.png" dosyasına yazdık ama acaba o dosya nerede? Tabii ki Octave hangi klasörü çalışma klasörü olarak aldıysa orada... Peki o klasörün o anda hangi klasör olduğunu nasıl anlarız? "Print Working Directory" (Çalışma klasörünü yazdır) komutunun baş harfleri olan pwd
komutuyla! 8)
pwd