Wednesday, November 4, 2015

R Basics 4 - Lists

Context: R has two types of vector

Atomic vectors contain values
These values are all of the same type.
They are arranged contiguously.
Atomic vectors cannot contain objects. 
There are six types of atomic vector: raw, logical, integer, numeic, complex and character.

Recursive vectors contain objects
R has two types of recursive vector: : list, expression.

Lists
- At top level: 1-dim indexed object that contains objects (not values)
- Indexed from 1 to length(list)
- Contents can be of different types
- Lists can contain the NULL object
- Deeply nested listed of lists possible
- Can be arbitrarily extended (not fixed)

List creation: usually using list()
> l1 <- list('cat', 5, 1:10, FALSE);l1
[[1]]
[1] "cat"

[[2]]
[1] 5

[[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[4]]
[1] FALSE

> l2 <- list ( x='dog', y=5+2i, z=3:8 );l2
$x
[1] "dog"

$y
[1] 5+2i

$z
[1] 3 4 5 6 7 8

> l3 <- c(l1, l2);l3
[[1]]
[1] "cat"

[[2]]
[1] 5

[[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[4]]
[1] FALSE

$x
[1] "dog"

$y
[1] 5+2i

$z
[1] 3 4 5 6 7 8

> l4 <- list(l1, l2);l4
[[1]]
[[1]][[1]]
[1] "cat"

[[1]][[2]]
[1] 5

[[1]][[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[1]][[4]]
[1] FALSE


[[2]]
[[2]]$x
[1] "dog"

[[2]]$y
[1] 5+2i

[[2]]$z
[1] 3 4 5 6 7 8


> l5 <- as.list( c(1,2,3));l5
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

> origL <- l4
> inserVorL <- l5
> position <- 3
> l6 <- append(origL, inserVorL, position);l6
[[1]]
[[1]][[1]]
[1] "cat"

[[1]][[2]]
[1] 5

[[1]][[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[1]][[4]]
[1] FALSE


[[2]]
[[2]]$x
[1] "dog"

[[2]]$y
[1] 5+2i

[[2]]$z
[1] 3 4 5 6 7 8


[[3]]
[1] 1

[[4]]
[1] 2

[[5]]
[1] 3

Basic information about lists
> dim(l)
NULL
> is.list(l)
[1] TRUE
> is.vector(l)
[1] TRUE
> is.recursive(l)
[1] TRUE
> is.atomic(l)
[1] FALSE
> is.factor(l)
[1] FALSE
> length(l)
[1] 5
> names(l)
NULL
> mode(l)
[1] "list"
> class(l)
[1] "list"
> typeof(l)
[1] "list"
> attributes(l)
NULL

The contents of a list
> print(l)
[[1]]
[[1]][[1]]
[1] "cat"

[[1]][[2]]
[1] 5

[[1]][[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[1]][[4]]
[1] FALSE


[[2]]
[[2]]$x
[1] "dog"

[[2]]$y
[1] 5+2i

[[2]]$z
[1] 3 4 5 6 7 8


[[3]]
[1] 1

[[4]]
[1] 2

[[5]]
[1] 3

> str(l)
List of 5
 $ :List of 4
  ..$ : chr "cat"
  ..$ : num 5
  ..$ : int [1:10] 1 2 3 4 5 6 7 8 9 10
  ..$ : logi FALSE
 $ :List of 3
  ..$ x: chr "dog"
  ..$ y: cplx 5+2i
  ..$ z: int [1:6] 3 4 5 6 7 8
 $ : num 1
 $ : num 2
 $ : num 3
> dput(l)
list(list("cat", 5, 1:10, FALSE), structure(list(x = "dog", y = 5+2i, 
    z = 3:8), .Names = c("x", "y", "z")), 1, 2, 3)
> head(l)
[[1]]
[[1]][[1]]
[1] "cat"

[[1]][[2]]
[1] 5

[[1]][[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[1]][[4]]
[1] FALSE


[[2]]
[[2]]$x
[1] "dog"

[[2]]$y
[1] 5+2i

[[2]]$z
[1] 3 4 5 6 7 8


[[3]]
[1] 1

[[4]]
[1] 2

[[5]]
[1] 3

> tail(l)
[[1]]
[[1]][[1]]
[1] "cat"

[[1]][[2]]
[1] 5

[[1]][[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[1]][[4]]
[1] FALSE


[[2]]
[[2]]$x
[1] "dog"

[[2]]$y
[1] 5+2i

[[2]]$z
[1] 3 4 5 6 7 8


[[3]]
[1] 1

[[4]]
[1] 2

[[5]]
[1] 3

Trap: cat(x) does not work with lists

Indexing [ versus [[ versus $
- Use [ to get/set multiple items at once
Note: [ always returns a list
- Use [[ and $ to get/set a specific item
- $ only works with named list items
all same: $name $"name" $'name' $`name`
- indexed by positive numbers: these ones
- indexed by negative numbers: not these
- indexed by logical atomic vector: in/out
an empty index l[] returns the list
Tip: When using lists, most of the time you wnat ot index with [[ or $; and avoid [

Indexing examples: one-dimension get
> j <- list(a='cat', b=5, c=FALSE)
> x <- j$a;x
[1] "cat"
> x <- j[['a']];x
[1] "cat"
> x <- j['a'];x
$a
[1] "cat"
> x <- j[[1]];x
[1] "cat"
> x <- j[1];x
$a
[1] "cat"

Indexing examples: set operations
- Start with example data
l <- list(x='a', y='b', z='c', t='d')
- Next use [[ or $ because specific selection
> l[[6]] <- 'new';
> names(l)[5] <- 'w'
> l$w <- 'new-W'
> l[['w']] <- 'dog'
- Change named values: note order ignored
> l[names(l) %in% c('t', 'x')] <- c(1,2)
> l
$x
[1] 1

$y
[1] "b"

$z
[1] "c"

$t
[1] 2

$w
[1] "dog"

[[6]]
[1] "new"

Indexing example: multi-dimension get
- Indexing evaluated from left to right
- Let's start with some example data...
> i <- c('aa', 'bb', 'cc')
> j <- list(a='cat', b=5, c=FALSE)
> k <- list(i, j);k
[[1]]
[1] "aa" "bb" "cc"

[[2]]
[[2]]$a
[1] "cat"

[[2]]$b
[1] 5

[[2]]$c
[1] FALSE


> k[[1]]
[1] "aa" "bb" "cc"
> k[[2]]
$a
[1] "cat"

$b
[1] 5

$c
[1] FALSE

> k[1]
[[1]]
[1] "aa" "bb" "cc"

> k[2]
[[1]]
[[1]]$a
[1] "cat"

[[1]]$b
[1] 5

[[1]]$c
[1] FALSE

> x <- k[[1]][[1]];x
[1] "aa"
> x <- k[[1]][[2]];x
[1] "bb"
> x <- k[1][1][1][1][1];x
[[1]]
[1] "aa" "bb" "cc"

> x <- k[1][2];x
[[1]]
NULL

> x <- k[[2]][1];x
$a
[1] "cat"

List manipulation
1 Arithmetic operators cannot be applied to lists (as content types can vary)
2 Use the apply() functions to apply a function of each element in a list:
> x <- list(a=1, b=month.abb, c=letters)
> lapply(x, FUN=length)
$a
[1] 1

$b
[1] 12

$c
[1] 26

> sapply(x, FUN=length)
 a  b  c 
 1 12 26 
y <- list(a=1, b=3, c=3, c=4)
sapply(y, FUN=function=(x,p) x^p, p=2)
sapply(y, FUN=function=(x,p) x^p, p=2:3)
3 Use unlist to convert list ot vector
> unlist(x)
    a    b1    b2    b3    b4    b5    b6    b7    b8    b9   b10   b11   b12    c1    c2    c3    c4    c5    c6    c7 
  "1" "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"   "a"   "b"   "c"   "d"   "e"   "f"   "g" 
   c8    c9   c10   c11   c12   c13   c14   c15   c16   c17   c18   c19   c20   c21   c22   c23   c24   c25   c26 
  "h"   "i"   "j"   "k"   "l"   "m"   "n"   "o"   "p"   "q"   "r"   "s"   "t"   "u"   "v"   "w"   "x"   "y"   "z" 

unlist wont unlist non-atomic 
4 Remove NULL objects from a list
> z <- list(a=1:9, b=letters, c=NULL)
> zNoNull <- Filter(Negate(is.null), z)
> zNoNull
$a
[1] 1 2 3 4 5 6 7 8 9

$b
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"

5 Use named lists to return multiple values

6 Factor index treated as integer
decode with v[as.character(f)]

No comments:

Post a Comment

Blog Archive