Bölüm 6 Listeler

Bir önceki konuda vektörlerin tek bir temel obje tipinden oluştuğunu söyledik. Listeler bu açıdan vektörlerden farklıdır ve birden fazla obje tipini içerebilir.

İlk olarak bir liste oluşturalım:

mylist = list(1, 2, TRUE, 'a')
mylist
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] TRUE
## 
## [[4]]
## [1] "a"

Bu sefer vektörlerde karşılaştığımız tür dönüştürme davranışı işe karşılaşmadık ve her eleman ilk girdiğimiz şekilde kaldı. Şimdi listenin 1. elemanına ulaşalım:

mylist[1]
## [[1]]
## [1] 1

Ne yazık ki eğer listemizin birinci elemanı ile işlem yapmak istiyorsak, bu doğru bir yöntem değil. Çünkü şu anda hala 1. elemana ulaşmadık. Listelerde her eleman bir tutucu olup, bir eleman içindeki değere ulaşmak istiyorsak çift köşeli parantez kullanmamız gerekir. Farkı daha iyi görebilmek için:

mylist[1]*5
## Error in mylist[1] * 5: non-numeric argument to binary operator
class(mylist[1])
## [1] "list"
mylist[[1]]
## [1] 1
mylist[[1]]*5
## [1] 5

İlk olarak listenin birinci elemanına tek köşeli parantez ile ulaşabileceğimizi varsayıp, 5 ile çarpmaya çalıştık. Ancak hata aldık. class() fonksiyonunu kullanıp gördük ki, tek köşeli parantez kullandığımda elde ettiğim obje hala bir liste. Listenin elemanının içinde depolanan bilgiye erişmek içinse iki tane köşeli parantez kullandım ve bu durumda 5 ile çarpabildim.

6.1 Listele indisleri

Listelerin diğer çok bariz olmayan özelliklerine bakalım. Örneğin, listemizin 4.elemanından kurtulmak isteyelim:

mylist[-4]
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] TRUE

Ya da

mylist[1:3]
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] TRUE

Bunlar tam olarak beklediğimiz gibi davranıyor ve 4. elemanı eksik liste elde ediyoruz. Peki çift köşeli parantez kullanarak, ilk üç elemandan oluşan bir vektör elde edebilir miyiz?

mylist[[1:3]]
## Error in mylist[[1:3]]: recursive indexing failed at level 2

6.2 Listeyi vektöre dönüştürmek

Hayır. İşe yaramadı. Peki bu ne demek, listeden asla vektör oluşturamaz mıyız? Hep liste olarak mı kalacak? Hayır, bunun için de as.vector() fonksiyonunu kullanabiliriz.

as.vector(mylist, mode = 'numeric')
## Warning in as.vector(mylist, mode = "numeric"): NAs introduced by coercion
## [1]  1  2  1 NA
as.vector(mylist, mode = 'character')
## [1] "1"    "2"    "TRUE" "a"

Bu fonksiyonlar varsa da çok kullanıldıklarını söyleyemem. Her veri türünün kendine özgü avantaj ve dezavantajları var ve farklı tür veri için belli veri tipleri daha uygun olacaktır. Genelde dönüştürmeler kimi fonksiyonlar sadece vektör, ya da sadece liste tipinde objelerle çalışıyorsa gerekli olabilir. Onun dışında listeden vektöre dönüştürme işlemleri kafa karıştırıcı olabilir. Bunun bir sebebi de listelerin elemanlarının tek bir elemandan oluşma zorunluluğunun olmamasıdır.

mylist2 = list(0, c(1, 2), T, 'a')
mylist2
## [[1]]
## [1] 0
## 
## [[2]]
## [1] 1 2
## 
## [[3]]
## [1] TRUE
## 
## [[4]]
## [1] "a"

Bu örnekte, listemizin ikinci elemanında iki elemanlı bir vektör sakladık. Şimdi az önceki yöntemi kullanmaya çalışırsak:

as.vector(mylist2, mode = 'numeric')
## Error in as.vector(mylist2, mode = "numeric"): 'list' object cannot be coerced to type 'double'
as.vector(mylist2, mode = 'character')
## [1] "0"       "c(1, 2)" "TRUE"    "a"

İkisi de beklediğimiz gibi bir sonuç değil. Eğer ki elde etmek istediğimiz vektör c('0', '1', '2', 'T', 'a') vektörü ise, unlist() fonksiyonunu kullanabiliriz.

unlist(mylist2)
## [1] "0"    "1"    "2"    "TRUE" "a"

6.3 Listelerde aritmetik işlemler

Şimdi bir de vektörler üzerinde yaptığımız işlemler listeler üzerinde de geçerli mi ona kısaca göz atalım. İlk olarak eşlenik olarak değerlendirebileceğimiz bir vektör objesi (myvec) ve liste objesi (mylist) yaratalım:

myvec = 1:3
myvec
## [1] 1 2 3
mylist = list(1, 2, 3)
mylist
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] 3

Vektörler konusunda gördüğümüz kimi işlemlerin üzerinden geçip, listeler üzerinde de geçerli olup olmadıklarına bakalım. İlk olarak birleştirme işlemi:

c(myvec, myvec)
## [1] 1 2 3 1 2 3
c(mylist, mylist)
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2
## 
## [[3]]
## [1] 3
## 
## [[4]]
## [1] 1
## 
## [[5]]
## [1] 2
## 
## [[6]]
## [1] 3

Yani, evet! Listeleri de birleştirebiliyoruz. Peki aritmetik işlemler?

myvec * 3
## [1] 3 6 9
mylist * 3
## Error in mylist * 3: non-numeric argument to binary operator

Hayır, aritmetik işlemleri yapabilmek için listenin elemanlarına tek tek erişmeliyiz.

6.4 İsimlendirilmiş liste

names(myvec) = c('a', 'b', 'c')
myvec
## a b c 
## 1 2 3
names(mylist) = c('a', 'b', 'c')
mylist
## $a
## [1] 1
## 
## $b
## [1] 2
## 
## $c
## [1] 3

Evet, isimlendirme de çalışıyor! Peki isimli listede alt küme alma işlemleri nasıl oluyor?

myvec['a']
## a 
## 1
mylist['a']
## $a
## [1] 1
mylist[['a']]
## [1] 1

Aynı indismiş gibi isimleri kullanarak da liste elemanlarına ulaşabiliyoruz. Ancak listelerde aynı amaçla kullanabileceğimiz başka bir operatör daha var: $

mylist$a
## [1] 1

Ve bu operatör çift köşeli paranteze denk işliyor, görüdüğünüz gibi liste tipinde bir obje değil, direkt olarak ilk eleman içine kaydedilen bilgiye ulaştık. Peki bu vektörlerde de çalışır mı?

myvec$a
## Error in myvec$a: $ operator is invalid for atomic vectors

Hayır!