Chapter 5

Changing Values in Place

vec <- c(0, 0, 0, 0, 0, 0)
vec
[1] 0 0 0 0 0 0
vec[1]
[1] 0
vec[1] <- 1000
vec
[1] 1000    0    0    0    0    0
vec[c(1, 3, 5)] <- c(1, 1, 1)
vec
[1] 1 0 1 0 1 0
vec[4:6] <- vec[4:6] + 1
vec
[1] 1 0 1 1 2 1
vec[7] <- 0
vec
[1] 1 0 1 1 2 1 0

Start by creating a deck of cards:

FACE <- c("king", "queen", "jack", "ten", "nine", "eight", "seven", "six", "five", "four", "three", "two", "ace")
SUIT <- c("spades", "clubs", "diamonds", "hearts")
VALUE <- 13:1
deck <- data.frame(face = rep(FACE, 4), suit = rep(SUIT, each = 13), value = rep(VALUE, times = 4))
library(DT)
datatable(deck)

Add a Variable

deck2 <- deck
deck2$new <- 1:52
datatable(deck2)

deck2$new <- NULL
head(deck2)
   face   suit value
1  king spades    13
2 queen spades    12
3  jack spades    11
4   ten spades    10
5  nine spades     9
6 eight spades     8

Change Particular Values

deck2[c(13, 26, 39, 52), ]
   face     suit value
13  ace   spades     1
26  ace    clubs     1
39  ace diamonds     1
52  ace   hearts     1
deck2[c(13, 26, 39, 52), "value"]
[1] 1 1 1 1
deck2[c(13, 26, 39, 52), 3]
[1] 1 1 1 1
deck2$value[c(13, 26, 39, 52)]
[1] 1 1 1 1
deck2$value[c(13, 26, 39, 52)] <- c(14, 14, 14, 14)
deck2$value[c(13, 26, 39, 52)]
[1] 14 14 14 14
# OR
deck2$value[c(13, 26, 39, 52)] <- 14
deck2$value[c(13, 26, 39, 52)]
[1] 14 14 14 14

Recall shuffle()

This function still need some work…

shuffle <- function(cards) {
 random <- sample(1:52, size = 52)
 cards[random, ]
}
deck3 <- shuffle(deck)
datatable(deck3)

Logical Operators

1 > 2
[1] FALSE
1 > c(0, 1, 2)
[1]  TRUE FALSE FALSE
c(1, 2, 3) == c(3, 2, 1)
[1] FALSE  TRUE FALSE
1 %in% c(3, 4, 5)
[1] FALSE
c(1, 2) %in% c(3, 4, 5)
[1] FALSE FALSE
c(1, 2, 3) %in% c(3, 4, 5)
[1] FALSE FALSE  TRUE
c(1, 2, 3, 4) %in% c(3, 4, 5)
[1] FALSE FALSE  TRUE  TRUE

Exercise

Extract the face column of deck2 and test whether each value is equal to ace. As a challenge, use R to quickly count how many cards are equal to ace.

sum(deck2$face == "ace")
[1] 4
deck3$face == "ace"
 [1] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[23] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[34] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE
[45] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE

Change the value of ace to 14

deck3$value[deck3$face == "ace"] <- 14
datatable(deck3)

deck4 <- deck

Exercise

Assign a value of 1 to every card in deck4 that has a suit of hearts.

deck4$value[deck4$suit == "hearts"] <- 1
deck4$value[deck4$suit == "hearts"]
 [1] 1 1 1 1 1 1 1 1 1 1 1 1 1
datatable(deck4)

In hearts, the queen of spades has the most unusual value of all: she’s worth 13 points.

deck4$value[deck4$suit == "spades" & deck4$face == "queen"] <- 13
deck4$value[deck4$suit == "spades" & deck4$face == "queen"]
[1] 13
datatable(deck4)

Exercise

w <- c(-1, 0, 1)
x <- c(5, 15)
y <- "February"
z <- c("Monday", "Tuesday", "Friday")
w > 0 
[1] FALSE FALSE  TRUE
10 < x & x < 20
[1] FALSE  TRUE
y == "February"
[1] TRUE
all(z %in% c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))
[1] TRUE
deck5 <- deck

Change the value of all face cards to 10

deck5$value[deck5$face %in% c("king", "queen", "jack")] <- 10
datatable(deck5)

Missing Information

1 + NA
[1] NA
NA == 1
[1] NA
c(NA, 1:50)
 [1] NA  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
[24] 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
[47] 46 47 48 49 50
mean(c(NA, 1:50))
[1] NA
mean(c(NA, 1:50), na.rm = TRUE)
[1] 25.5
NA == NA
[1] NA
c(1, 2, 3, NA) == NA
[1] NA NA NA NA
is.na(NA)
[1] TRUE
vec <- c(1, 2, 3, NA)
is.na(vec)
[1] FALSE FALSE FALSE  TRUE
deck5$value[deck5$face == "ace"] <- NA
head(deck5, 13)
    face   suit value
1   king spades    10
2  queen spades    10
3   jack spades    10
4    ten spades    10
5   nine spades     9
6  eight spades     8
7  seven spades     7
8    six spades     6
9   five spades     5
10  four spades     4
11 three spades     3
12   two spades     2
13   ace spades    NA

Environments

library(pryr)
library(knitr)
parenvs(all = TRUE)
   label                            name               
1  <environment: R_GlobalEnv>       ""                 
2  <environment: package:pryr>      "package:pryr"     
3  <environment: package:DT>        "package:DT"       
4  <environment: package:knitr>     "package:knitr"    
5  <environment: package:stats>     "package:stats"    
6  <environment: package:graphics>  "package:graphics" 
7  <environment: package:grDevices> "package:grDevices"
8  <environment: package:utils>     "package:utils"    
9  <environment: package:datasets>  "package:datasets" 
10 <environment: package:methods>   "package:methods"  
11 <environment: 0xc07be8>          "Autoloads"        
12 <environment: base>              ""                 
13 <environment: R_EmptyEnv>        ""                 
as.environment("package:knitr")
<environment: package:knitr>
attr(,"name")
[1] "package:knitr"
attr(,"path")
[1] "/home/faculty/arnholtat/R/x86_64-pc-linux-gnu-library/3.2/knitr"
globalenv()
<environment: R_GlobalEnv>
baseenv()
<environment: base>
emptyenv()
<environment: R_EmptyEnv>

Next, you can look up an environment’s parent with parent.env:

parent.env(globalenv())
<environment: package:pryr>
attr(,"name")
[1] "package:pryr"
attr(,"path")
[1] "/home/faculty/arnholtat/R/x86_64-pc-linux-gnu-library/3.2/pryr"

Notice that the empty environment is the only R environment without a parent:

parent.env(emptyenv())
Error in parent.env(emptyenv()): the empty environment has no parent

You can view the objects saved in an environment with ls or ls.str. ls will return just the object names, but ls.str will display a little about each object’s structure:

ls(emptyenv())
character(0)
ls(globalenv())
 [1] "deck"    "deck2"   "deck3"   "deck4"   "deck5"   "FACE"    "shuffle"
 [8] "SUIT"    "VALUE"   "vec"     "w"       "x"       "y"       "z"      

You can use R’s $ syntax to access an object in a specific environment. For example, you can access deck from the global environment:

head(globalenv()$deck)
   face   suit value
1  king spades    13
2 queen spades    12
3  jack spades    11
4   ten spades    10
5  nine spades     9
6 eight spades     8

And you can use the assign function to save an object into a particular environment. First give assign the name of the new object (as a character string). Then give assign the value of the new object, and finally the environment to save the object in:

assign("NewObject", "Value of new object", envir = globalenv())
globalenv()$NewObject
[1] "Value of new object"

You can use environment to see the current active environment:

environment()
<environment: R_GlobalEnv>

Evaluation

R creates a new environment each time it evaluates a function. R will use the new environment as the active environment while it runs the function, and then R will return to the environment that you called the function from, bringing the function’s result with it. Let’s call these new environments runtime environments because R creates them at runtime to evaluate functions. We’ll use the following function to explore R’s runtime environments. We want to know what the environments look like: what are their parent environments, and what objects do they contain? show_env is designed to tell us:

show_env <- function(){
  list(ran.in = environment(),
       parent = parent.env(environment()),
       objects = ls.str(environment()))
}

show_env is itself a function, so when we call show_env(), R will create a runtime environment to evaluate the function in. The results of show_env will tell us the name of the runtime environment, its parent, and which objects the runtime environment contains:

a <- show_env()
a
$ran.in
<environment: 0x277e028>

$parent
<environment: R_GlobalEnv>

$objects
b <- a$ran.in
b
<environment: 0x277e028>

The results reveal that R created a new environment to run show_env() in. The environment had no objects in it, and its parent was the global environment.

Let’s run show_env again:

show_env()
$ran.in
<environment: 0x12ade08>

$parent
<environment: R_GlobalEnv>

$objects

You can look up a function’s origin environment by running environment on the function:

environment(PASWR2::z.test)
<environment: namespace:PASWR2>
environment(PASWR::z.test)
<environment: namespace:PASWR>
environment(BSDA::z.test)
<environment: namespace:BSDA>
environment(show_env)
<environment: R_GlobalEnv>

The Functions

setup <- function(deck) {
  DECK <- deck
  DEAL <- function() {
    card <- deck[1, ]
    assign("deck", deck[-1, ], envir = parent.env(environment()))
    card
  }
  SHUFFLE <- function(){
    random <- sample(1:52, size = 52)
    assign("deck", DECK[random, ], envir = parent.env(environment()))
  }
  list(deal = DEAL, shuffle = SHUFFLE)
}
cards <- setup(deck)
deal <- cards$deal
shuffle <- cards$shuffle

Where Is All of This?

setup
function(deck) {
  DECK <- deck
  DEAL <- function() {
    card <- deck[1, ]
    assign("deck", deck[-1, ], envir = parent.env(environment()))
    card
  }
  SHUFFLE <- function(){
    random <- sample(1:52, size = 52)
    assign("deck", DECK[random, ], envir = parent.env(environment()))
  }
  list(deal = DEAL, shuffle = SHUFFLE)
}
environment(setup)
<environment: R_GlobalEnv>
deal
function() {
    card <- deck[1, ]
    assign("deck", deck[-1, ], envir = parent.env(environment()))
    card
  }
<environment: 0x33b9f80>
environment(deal)
<environment: 0x33b9f80>
shuffle
function(){
    random <- sample(1:52, size = 52)
    assign("deck", DECK[random, ], envir = parent.env(environment()))
  }
<environment: 0x33b9f80>
environment(shuffle)
<environment: 0x33b9f80>

Playing Cards Now

shuffle()
deal()
    face  suit value
15 queen clubs    12
deal()
    face   suit value
41 queen hearts    12
deal()
   face  suit value
21  six clubs     6
deal()
   face   suit value
44 nine hearts     9
deal()
    face   suit value
46 seven hearts     7