26 Şubat 2016 Cuma

R Programlama Temelleri

R Programlama Temelleri

Baktım ki ne zamandır blog a bir şeyler eklemiyorum ve ne zamandır bir çok şey eklemişim birikimlerime.  R Programlama dilinin temel yapısını anlatacağım.

R Programlama dili java, c# gibi yorumlayıcı tabanlı bir dildir. Temel hedefi istatistiksel işlemler ve veri analizinde  kullanılması amaçlanmıştır. (veri madenciliği, grafikleme vs.). SPSS, Matlab'ın data analiz bölümleri, Weka vs. ile karşılaştırılabilir. Ayrıca R Programlama dili ile C, Python, C++, .net gibi dillerde yazılmış fonksiyonlarıda çağırabiliyoruz..

Ücretsiz olarak GNU lisansı ile dağıtımı yapıldığı için istediğiniz yerde kullanabilirsiniz. Windows, Linux, Unix için dağıtımı mevcut.

Avantajlarını, son yıllarda popüleritesinin artmasını vs. yazmayacağım. Bunları zaten internette bulabilirsiniz. Türkçe kaynağı arttırmak amaçlı bu yazı dizisini yazacağım. Umarım insanlara faydamız dokunur.

Şu adresten işletim sisteminize uygun olanı indirin ve kurun : https://www.r-project.org/

Kurulumdan sonra programı açtığımızda ilk olarak karşımıza aşağıdaki gibi bir konsol ekranı gelebilir.:


Aşağıda ilk kod testlerimizi görebilirsiniz ("Merhaba Dünya" yazdırmadan olmaz değil mi :) ):

> print("Merhaba Dünya")
[1] "Merhaba Dünya"
> print(33.5 + 11.2/11.2*10)
[1] 43.5

Yukarıkida iki ">" büyüktür göstergeli kodları satır satır yazın. Sonuçların aynı olması gerek.

R programlama dilinin dil yapısına uygun bir şekilde değişken aşağıdaki gibi tanımlanır:

> BenimDegiskenim <- "burakgokalp.com"
> BenimIkinciDegiskenim <- "www.burakgokalp.com"

> print (BenimDegiskenim)
[1] "burakgokalp.com"
> print (BenimIkinciDegiskenim)
[1] "www.burakgokalp.com"


Diğer genel amaçlı dillerden farklı olarak "=" eşitlik işareti haricinde <- işareti ile sağdan sola aktarım gerçekleşebiliyor. Yazdığımız kod topluluklarını bir script haline getirebiliyoruz. Kod topluluğunu bir txt dosyasına yazın.Örneğin kodumuz bu olsun :

BenimDegiskenim <- "Burak Gökalp ile kısa kısa R programlama"
print (BenimDegiskenim)

Daha sonra bu kodlarla dolu txt dosyasını makinanın herhangi bir yerine deneme.r diye ansi karakter kodlaması ile kaydedin. Linux terminalde Rscript deneme.r şeklinde windows'da ise Rscript.exe  ile bu işi yapabilirsiniz. Aşağıda örnek bir R Script örneği denemesi bulunmaktadır:

C:\Program Files\R\R-3.2.3\bin\x64>Rscript deneme.r
[1] "Burak Gökalp ile kısa kısa R programlama"



R Programlama dilinde basit veri tipleri (vectorlerin sınıfları diyede geçer) aşağıdaki gibidir:

  1. Numeric
  2. Integer
  3. Complex
  4. Logical
  5. Character
Bunun haricinde birde raw data vardır ki bunu dahil etmiyorum. Yukarıdaki tipler, vectorlerde sakalnabilecek veri tipleridir.

1. Numeric

Numeric sayı tipi aslında ondalıklı (decimal) sayı tipini temsil eder. Bir kaç örnek test edelim

> numerik <- 32.4
> tamSayi <- 23
> 
> print(class(numerik))
[1] "numeric"
> print(class(tamSayi))
[1] "numeric"

tamSayi değişkenine gerçektende tamsayı aktarmamıza rağmen niye numeric olarak atanmaktadır? Bu sorunun cevabı için integer değişkenlere geçelim

2. Integer

Bir integer değişken oluşturmak için "as.integer()" fonksiyonunu çağırmamız gerek. Aşağıdaki örnekte büyük küçük harf ayrımı yapan R Programlama dili ile iki adet değişken tanımlayıp atama yapıyoruz.

> tamSayi = 30
> tamsayi = as.integer(31)
> tamSayi
[1] 30
> tamsayi
[1] 31
> class(tamSayi)
[1] "numeric"
> class(tamsayi)
[1] "integer"

Görüldüğü gibi tamSayi ile tamsayi arasındaki numeric ve integer tipi farkı sadece atama yapılırken oluşturuluyor. as.integer() fonksiyonu ile istersek character tipindeki tanımlanmış tam sayılarıda alabiliriz.

> tamsayi = as.integer(31.645)
> tamsayi
[1] 31
> #string değerlerdende sayıları alabiliriz örneğin:
> print(as.integer("31.645"))
[1] 31

3. Complex

Sanal değerli (karmaşık sayılar) sayılar için kullanılan bir değişkendir. Aşağıdaki örneklerden temel kullanımları çıkarabilirsiniz:


> z =  1 + 21i    ##karmaşık bir sayı oluşturalım
> z
[1] 1+21i
> class(z)
[1] "complex"
> sqrt(z)
[1] 3.318418+3.164158i
> sqrt(as.complex(-1))
[1] 0+1i

4. Logical

Mantıksal "True" (Doğru) ya da "False" (Yanlış) değerlerini saklamak için kullnılır. Bunun için iki stringi karşılaştırma yaparak sonucunu başka bir değişkene yazdıralım

> isim = "burak"
> isim2 = "Burak"
> sonuc = isim == isim2
> class sonuc
Hata: unexpected symbol in "class sonuc"
> class(sonuc)
[1] "logical"
> sonuc
[1] FALSE
> isim = "Burak"
> sonuc = isim == isim2
> sonuc
[1] TRUE
> class(sonuc)
[1] "logical"

Görüldüğü gibi, isterse as.integer gibi as.logical gibi bir fonksiyonlar değişkenlerin mantıksal değerini alabiliriz. Aşağıdaki gibi bir örnekle bunun kullanımını görebiliriz.

> sonuc = as.logical(21)
> sonuc
[1] TRUE
> sonuc = as.logical(0)
> sonuc
[1] FALSE
> sonuc = as.logical(-3)
> sonuc
[1] TRUE


5. Character

Karakter ve string tipindeki değişkenleri tanımlamak için kullanılır. Aşağıda yaptığım örnekte string birleştirme, tip dönüşümü gibi olduğunu görebilirsiniz.


> x = as.character(3.14)
> x
[1] "3.14"
> class(x)
[1] "character"
> pi = as.numeric(x)
> pi
[1] 3.14
> class(pi)
[1] "numeric"
> # iki adet karakter aşağıdaki karakter ekleme fonksiyonu ile eklenebilir
> print(paste(pi, " ", x))
[1] "3.14   3.14"
> #ANSI C'den aşina olduğumuz sprintf fonksiyonu R Programlama
> #dilindede aynı şekilde kullanabiliyoruz
> sprintf("pi nin tipi %s, x in tipi %s", class(pi), class(x))
[1] "pi nin tipi numeric, x in tipi character"
> 


R Programlama dilinde değişkenler dinamik tiplidirler. Bir ansi C veya java gibi veri tipini belirtmeye gerek yoktur. Bir betik dili olan PHP gibi değişkenlerin tipleri yorumlayıcı tarafından belirlenir. Tip dönüşümlerini el yordamıyla değiştirmek için gerekli fonksiyonları zaten belirttik.


Ne kadar çoğu yerde "data type" veya "r-object" olarak nitelendirilseler de ben aşağıdaki yapılara "R Dilindeki Veri Yapıları" şeklinde tanımlama yapmak istiyorum.

Vector
List
Matrix
Array
Factor

Şimdi bunların kısa kısa neler olduğunu, nasıl tanımlandıklarını ve örnek kullanımlarını açıklayalım.

 

Vector : 

 Vector'ler c() fonksiyonu ile tanımlanırlar. c() fonksiyonu arguman olarak aldığı tüm nesneleri oluşturacağı vector'e ekler.

> vectorBurak = c("b", "u", "r", "a", "k")
> vectorBura
Hata: 'vectorBura' nesnesi bulunamadı
> vectorBurak
[1] "b" "u" "r" "a" "k"
> class(vectorBurak)
[1] "character"

Görüldüğü gibi vectorün sınıf tipi içeriğinde sakladığı verilerin tipi olan "character" olarak gözükmektedir. c() fonksiyonu veya herhangi bir fonksiyonun kullanımı ya da herhangi bir veri tipi hakkında bilgi için konsola help(c), help(as.integer), help(character) vs... yazarak merakınızı giderebilirsiniz.

Şimdi vectorler ile birlikte birkaç işlem yapalım.

> a = c(3, 5, 8)
> b = c(7, 5, 2)
> a
[1] 3 5 8
> b
[1] 7 5 2
> 2*a
[1]  6 10 16
> a
[1] 3 5 8
> a = 2*a
> print(a)
[1]  6 10 16
> class(a)
[1] "numeric"
> a <- a/2
> c = a + b
> print(c)
[1] 10 10 10

Yukarıda a ve b vektörleri oluşturuyoruz. a ve b vektörlerinin içeriklerini kendilerini çağırarak ya da print(a) veya print(b) şeklindede yazdırabiliriz. Ben a ve b yi direk çağırarak içeriklerini yazdırdım. Daha sonra 2*a diyerek, a vektörünün içeriğindeki tüm elementleri 2 ile çarpıp sonucu çağırarak yazdırdım. Daha sonra a'nın içerğini
a = 2*a
a <- a/2
Şeklinde a yı eski haline getirdik. Bu işlemler ne kadar "amaçsız" gibi gözüksede aslında değişkenlerde olan değişiklikleri size göstermek yapmaktayım.

> c = a + b
Yukarıdaki satırda a ve b vektörlerinin her bir elementini toplayarak, toplanmış elementlerden yeni bir vektör oluşturuyoruz. Bunun adınada c dedik. "c" nin içeriğine baktığımızda "a" 'nın
> a
[1] 3 5 8

ve "b" nin
> b
[1] 7 5 2

elementlerinin toplamı olduğu görülmektedir. 
3+7 = 10, 
5+5 = 10,
8+2 = 10

> print(c)
[1] 10 10 10

Bu şekilde toplama işlemi, çarpma işlemi, çıkarma işlemi ve bölme işlemi vektörler arasında yapabiliriz. Ancak vektörlerin uzunlukları (eleman sayıları) farklı olduğunda işler biraz değişmekte. Öncelikle uzun olan vektörün eleman sayısı, kısa olan elemanın eleman sayısının katları olmak zorundadır.
Farklı uzunluktaki vektörler biribiri ile eşleşsin diye, kısa olan vektörün elemanları, boşlukları doldurmak için geri dönüşümlü kullanılır. Aşağıdaki örnek ve açıklama daha açıklayıcı olacaktır sanırım.
> b = c(10, 20, 30)
> a = c(1, 2, 3, 4, 5, 6, 7, 8, 9)
> a + b
[1] 11 22 33 14 25 36 17 28 39
> a * b
[1]  10  40  90  40 100 180  70 160 270
> b / a
[1] 10.000000 10.000000 10.000000  2.500000  4.000000  5.000000  1.428571
[8]  2.500000  3.333333
> a - b
[1]  -9 -18 -27  -6 -15 -24  -3 -12 -21

Yukarıdaki örnekte görüldüğü gibi 3 elemana sahip b vektörü ile 9 elemana sahip a vektörü oluşturulmuştur. 9 sayısı 3 ün tam katıdır...
> b = c(10, 20, 30)
> a = c(1,   2,  3, 4, 5, 6, 7, 8, 9)

Öncelikle toplama işlemi sonucuna bakalım. Toplama işleminde ilk üç eleman toplamı normal bir toplamadan ibarettir.
> a + b
[1] 11 22 33 14 25 36 17 28 39

Yukarıdaki işlem b vektöründeki elemanların 2 kere daha yeniden kullanılmasıyla yapılır. Yani aşağıdaki gibi bir dönüşüme uğradığını farz edebiliriz.

> b = c(10, 20, 30, 10, 20, 30, 10, 20, 30)
> a = c(1,   2,  3,  4,  5,  6,  7,  8,  9)

Altı çizilen yerler yeniden kullanılan yerler olarak görüldüğünde toplam sonucunun sutun sutun alt alta yapıldığını anlayabiliriz:

> a + b
[1] 11 22 33 14 25 36 17 28 39

Diğer aritmetik işlemlerdede bir değişiklik olmayacak ve aynı yapı kullanılacaktır. Yani eksik yerlerde elemanlar tekrar edilerek işleme alınacaktır.

> a * b
[1]  10  40  90  40 100 180  70 160 270
> a - b
[1]  -9 -18 -27  -6 -15 -24  -3 -12 -21


Vectorlerde indexler diğer programlama dillerinin aksine 0 yerine 1 den başlamaktadır. Vektorlerde indexler diğer dillerdeki gibi köşeli parantezler ile kullanılır. a[1] gibi...

Aşağıda yazdığım örneklere bakalım:

> a = c(1, 2, 3, 4, 5, 6, 7, 8, 9)
> a[1]
[1] 1
> a[2]
[1] 2
> a[3]
[1] 3
> a[0]
numeric(0)
> a[-3]
[1] 1 2 4 5 6 7 8 9
> a
[1] 1 2 3 4 5 6 7 8 9
> 

Yukarıda görüldüğü gibi indexler diğer dillerin aksine 0 dan başlamaz. R Programlama dilinde diğer dillerin aksine birde negatif index kullanımıda mümkündür. Negatif index kullanımında, belirtilen değerin mutlak değerindeki eleman ayrıştırılarak o şekilde gösterim sağlanır. Yukarıda görüldüğü gibi a[-3] yazıldığında a vektörünün 3. elemanı hariç tüm elemanları gösterilmektedir..

> a[-3]
[1] 1 2 4 5 6 7 8 9
> a
[1] 1 2 3 4 5 6 7 8 9


Vectorlerde birden fazla elemanıda numeric indexli vectorler ilede çağırabiliriz. Yani dizi içinde belirlediğimiz indexlerdeki elemanları seçerek yeni bir dizi çağırmak gibi düşünülebilir.


> a = c(1, 2, 3, 4, 5, 6, 7, 8, 9)
> a
[1] 1 2 3 4 5 6 7 8 9
> b = a[c(1,4,9)]
> print(b)
[1] 1 4 9

Görüldüğü gibi diğer dillerdeki gibi indexlerde bir değil birden fazla index kullanarak esnekliğimizi arttırabiliriz. Yani vector çağırırken, vectorler yardımıyla index belirliyoruz. İndex için kullandığımız vectörde, index numaraları sıralı olmak zorunda değil ya da tekrar eden numaralarda kullanılabilir.

Örnek aşağıdaki gibidir;

> a[c(3,2,1,3,3)]
[1] 3 2 1 3 3

Ayrıca aralık operatörü ile aşağıdaki gibi bir kullanım ile bu iki index numarası ve arasındaki numaralardaki elemanlarda seçilebilir:

> a[5:2]
[1] 5 4 3 2
> a[2:5]
[1] 2 3 4 5

Aralık için belirlenen sayıların büyükten küçüğe ve küçükten büyüğe olması mümkündür.

Isimlendirilmiş Vectorler:

Bu vektörlere aslında php'de array kullananlar aşinadır.R programlama dilindede aynı şeye benzer bir tanımlama yapabiliriz.
> isimSoyisim <- c("Burak", "Gökalp")
> names(isimSoyisim) <- c("isim", "soyisim")
> isimSoyisim["isim"]
   isim 
"Burak" 
> isimSoyisim["soyisim"]
 soyisim 
"Gökalp" 
> isimSoyisim
    isim  soyisim 
 "Burak" "Gökalp" 

 Görüldüğü gibi names() fonksiyonu ile "isimSoyisim" vektörüne, özel isimlendirilmiş indexler atayabiliyoruz. Bu indexleri isimSoyisim["isim"] şeklinde kullanarak istediğimiz değere erişebiliriz.

Bu bir başlangıç olsun. Dersin devamını en yakın zamanda yazacağım. Kolay gelsin.