Οι λιστες (list) ειναι μια από τις ισχυρότερες δομές δεδομένων στην R. - είναι γενικές, δηλαδή μπορεί να περιέχουν δεδομένα διαφορετικού τύπου (κάτι που δεν έχουν τα vectors και matrices) - οι καταχωρήσεις μπορεί να έχουν όνομα (ισχύει και στα vectors αυτό) - οι καταχωρήσεις μπορεί να έχουν διαφορετικό μήκος (κάτι που δεν ισχύει στα data.frames)
Άρα μπορούμε να πούμε ότι οι list ειναι δομές δεδομένων που επιτρέπουν την αποθήκευση διαφορετικού τύπου μεταβλητών, οι καταχωρήσεις ειναι ονοματισμένες και η κάθε καταχώρηση μπορεί να έχει διαφορετικό μήκος.
a = list() # άδεια λίστα. H a ειναι μια λίστα που δεν περιέχει τίποτα
a = list(x=c(1,2,3)) # Η a ειναι μια λίστα που περιέχει ένα αντικείμενο, το x, που ειναι vector από 3 στοιχεία
a = list(x = c(1,2,3), y=c("A")) # Η a περιέχει 2 στοιχεία, το x και y, που το καθένα ειναι vector
## από αριθμούς και χαρακτήρες αντίστοιχα.
a = list( x = list(x=c("A"), z=c(1,2,3)), y = "kalimera") # Η a είναι μια λίστα , που περιέχει μια λίστα (την x), και ένα character-string το y. Η λιστα x, περιέχει δύο vectors
a = list(c(1,2,3)) # λίστα που περιέχει ένα vector, μη ονοματισμένο (χωρίς όνομα)
Βλέπετε από τα παραπάνω παραδείγματα πόσο ισχυρές ειναι οι λίστες.
Στις λίστες έχουμε δύο operators (δύο τρόπους) να έχουμε πρόσβαση στα στοιχεία της. Το [[ ]] και το []. Θεωρείστε το παρακάτω παράδειγμα.
x = list(a=c(1,2,3), b=c("A", 'b'))
Tότε, το πρώτο στοιχείο της λίστας x, ειναι το a, και το δευτερο στοιχείο της λίστας x είναι το b.
Έχουμε λοιπόν:
## first element
## Πρόσβαση με το όνομα του στοιχείου
x$a ## το στοιχείο του x, που έχει το όνομα a
## [1] 1 2 3
## Πρόσβαση με indexes
## Ώς vector
x[[1]] ## πρώτο στοιχείο ειναι το c(1,2,3) ΕΙΝΑΙ vector
## [1] 1 2 3
## Ως λίστα
x[1] ## πρώτο στοιχείο ΕΙΝΑΙ ΛΙΣΤΑ
## $a
## [1] 1 2 3
ΠΡΟΣΟΧΗ! Όταν έχουμε πρόσβαση ως λιστα δηλαδή με το [ ] operator, τότε μπορούμε να κάνουμε slice, δηλαδή να πάρουμε και πανω από ένα στοιχεία. Για παράδειγμα
a = list(x=c(1,2), y="a", z=c(5,4,5,3))
## μία λίστα με τα 2 πρώτα στοιχεία
a[1:2]
## $x
## [1] 1 2
##
## $y
## [1] "a"
## μία λίστα με τα στοιχεία 1,3
a[c(1,3)]
## $x
## [1] 1 2
##
## $z
## [1] 5 4 5 3
ΠΡΟΣΟΧΗ!!! Το a[[1:2]] ίσως δεν βγάλει λάθος, όμως ειναι αποτέλεσμα χωρίς νόημα!
a[[c(1,2)]]
## [1] 2
Προσέξτε τις διαφορές:
a = list(x=c(1,2,3), y=c("a", "b"))
## Το πρώτο στοιχείο (x)
a$x
## [1] 1 2 3
## Επίσης το πρώτο στοιχείο
a[["x"]] ## θα ειναι vector
## [1] 1 2 3
## Επίσης το πρώτο στοιχείο
a["x"] # Θα ειναι λίστα
## $x
## [1] 1 2 3
Παρατηρήστε την διαφορά
a$xa[["x"]](χωρίς και με εισαγωγικά)
To γεγονός ότι έχουμε πρόσβαση με τα ονόματα, μας επιτρέπει να τις χρησιμοοποιήσουμε ως associative arrays (hashes)
a=list(antonis=29, vaggelis=54, kostas=33)
# όπου σε κάθε όνομα έχουμε αποθηκευσει την ηλικία
# Ας υποθέσουμε ότι η λίστα έίχε εκατομμύρια καταχωρήσεις (αντί για μόνο 3)
Στην C δεν υπάρχει η δυαντότητα αυτή. Εκεί για να είχαμε τη σχέση μεταξύ ονόματος και ηλικίας θα έπρεπε:
nam = c("antonis", "vaggelis", "kostas")
age = c(29, 54, 33)
# όμως για να βρούμε τι ηληκία έχει ο Κώστας, θα πρέπει να διατρέχουμε όλη τη λίστα
# Στην R απλά θα γράφαμε
a$kostas
## [1] 33
Ένα δεύτερο συνηθισμένο παράδειγμα αφορά στην έκφραση γονιδίων. Σε έναν οργανισμό Α, που έχει 20,000 γονίδια, τα γονίδια a1, a2, a7 μας ενδιαφέρουν επειδή σχετίζονται με μία ασθένεια. Οι εκφράσεις γονιδίων στον Α, υπάρχουν σε μια λίστα ΕΑ. Για παράδειγμα, EA[["a1"]], δίδει την έκφραση του a1, στον Α. Αν θέλουμε να δούμε σε έναν οργανισμό Β, την έκφραση των τριων αυτών γονιδίων a1, a2, a7, θα πρέπει να διατρέξουμε όλη την λίστα των γονιδίων ΕΒ του B ώστε να βρούμε ποιες τιμές έκφρασης αντιστοιχούν στα γονίδια a1, a2, a7. Αν όμως έχουμε ονοματίσει την λίστα γονιδίων, τότε μπορούμε πολύ εύκολα να ζητήσουμε τις εκφράσεις ως εξής ΕΒ[["a1"]] ΕΒ[["a2"]] ΕΒ[["a7"]].
Γενικά οι ονοματισμένες λίστες ειναι πολύ χρήσιμες στην βιοπληροφορική
Και τα vectors μπορούν να φέρουν ονόματα στις τιμές που περιέχουν. Για παράδειγμα,
a = c(12,21,13) ## δεν φέρει ονόματα
names(a) = c("Gene1", "Gene2", "Gene3")
a
## Gene1 Gene2 Gene3
## 12 21 13
a["Gene1"] == a[1]
## Gene1
## TRUE
Η δομή matrix ειναι μια δισδιάστατη δομή δεδομένων. Μοιάζει με τα vectors. Έτσι:
Με default τιμή
## όλα τα κελιά της m θα έχουν την τιμή 0
m = matrix(0, nrow=5, ncol=3)
m
## [,1] [,2] [,3]
## [1,] 0 0 0
## [2,] 0 0 0
## [3,] 0 0 0
## [4,] 0 0 0
## [5,] 0 0 0
Με vector τιμών
m1 = matrix(1:10, nrow=5, ncol=2) ## δεκα τιμές σε δέκα κελιά
m1
## [,1] [,2]
## [1,] 1 6
## [2,] 2 7
## [3,] 3 8
## [4,] 4 9
## [5,] 5 10
m2 = matrix(1:10, nrow=5, ncol=2, byrow=TRUE)
m2
## [,1] [,2]
## [1,] 1 2
## [2,] 3 4
## [3,] 5 6
## [4,] 7 8
## [5,] 9 10
m3 = matrix(1:10, nrow=5, ncol=2, byrow=FALSE)
m3
## [,1] [,2]
## [1,] 1 6
## [2,] 2 7
## [3,] 3 8
## [4,] 4 9
## [5,] 5 10
# Ποια ειναι η default συμπεριφορά της R για το πώς να βάλει τις τιμές στα κελιά;
κυκλικά με vector τιμών
m1 = matrix(1:2, nrow=2, ncol=5, byrow=TRUE)
m1
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 1 2 1
## [2,] 2 1 2 1 2
m2 = matrix(1:2, nrow=2, ncol=5, byrow=FALSE)
m2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 1 1 1 1
## [2,] 2 2 2 2 2
Τι γίνεται αν το μέγεθος του matrix δεν ειναι πολλαπλάσιο του μήκους του vector
m = matrix(1:3, nrow=2, ncol=5)
## Warning in matrix(1:3, nrow = 2, ncol = 5): data length [3] is not a sub-
## multiple or multiple of the number of rows [2]
m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 3 2 1 3
## [2,] 2 1 3 2 1
Τι γίνεται αν το μέγεθος του matrix είναι μικρότερο από το μήκος του vector
m = matrix(1:15, nrow=2, ncol=5)
## Warning in matrix(1:15, nrow = 2, ncol = 5): data length [15] is not a sub-
## multiple or multiple of the number of rows [2]
m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 3 5 7 9
## [2,] 2 4 6 8 10
Στα matrix μπορούμε να έχουμε ονόματα γραμμών και στηλών
m = matrix(1:10, nrow=2, ncol=5, byrow=TRUE)
colnames(m) = letters[1:5]
rownames(m) = c("a", "aa")
m
## a b c d e
## a 1 2 3 4 5
## aa 6 7 8 9 10
Για να έχουμε πρόσβαση στα στοιχεία του matrix χρησιμοποιούμε τον operator [,]. Πριν το κόμμα ‘,’ αναφερόμαστε στις γραμμές και μετά το κόμμα στις στήλες. Για παράδειγμα:
a = matrix(1:10, nrow=2)
a[1,2] ## στοιχείο 1ης γραμμής 2ης στήλης
## [1] 3
a[1, 1:2] ## στοιχεία 1ης γραμμής, στήλης 1 και 2
## [1] 1 3
a[1:2, c(1,2,4)] # στοιχεία γραμμών 1,2 και στηλών 1,2,4. Θα ειναι matrix 2x3.
## [,1] [,2] [,3]
## [1,] 1 3 7
## [2,] 2 4 8
Αν υπάρχουν ονόματα γραμμών στηλών, τότε η πρόσβαση μπορεί να γίνει και με τα ονόματα
a = matrix(1:10, nrow=2)
colnames(a) <- letters[1:5]
rownames(a) <- c("x", "y")
a[,"c"] ## στοιχείο 1ης γραμμής 2ης στήλης
## x y
## 5 6
a["x",]
## a b c d e
## 1 3 5 7 9
ΠΑΡΑΤΗΡΗΣΗ: Για να πάρουμε όλη την γραμμή ή την στήλη χρησιμοποιούμε ‘άδεια’ θέση στις γραμμές ή στις στήλες. Δείτε το παράδειγμα παραπάνω.
To data.frame μοιάζουν με matrix όμως…
Ο πιο συνηθισμένος τρόπος να κατασκευάσουμε data.frame είναι με την συνάρτηση read.table, όπου διαβάζουμε δεδομένα που βρίσκονται σε αρχειο και έχουν μορφή πίνακα
##a = matrix(rnorm(20000, 1000, 10), nrow=200)
##colnames(a) = paste("Individual",1:100, sep="")
##rownames(a) = paste("Gene", 1:200, sep="")
##write.table(a, file="geneExpressionExample.csv", sep="\t", col.names=TRUE, row.names = F, quote = F)
## Διαβάζουμε το αρχείο με την συνάρτηση read.table
## Έχει επικεφαλίδα, άρα βάζουμε header=TRUE
a = read.table(file="geneExpressionExample.csv", header=TRUE)
dim(a) # οι Διαστάσεις του a
## [1] 200 100
head(a) # οι πρώτες έξι γραμμές