# Hand on Programming with R
# By Garrett Grolemund
setwd("C:\\Users\\Luis\\Desktop\\HandOnProgramming_R")
# Objects, R lets you save data by storing it inside an R objec
die <- 1:6
die
## [1] 1 2 3 4 5 6
# You can do inner multiplication with
# the %*% operator and
die%*%die
## [,1]
## [1,] 91
# outer multiplication with the %o% operator:
die%o%die
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 2 3 4 5 6
## [2,] 2 4 6 8 10 12
## [3,] 3 6 9 12 15 18
## [4,] 4 8 12 16 20 24
## [5,] 5 10 15 20 25 30
## [6,] 6 12 18 24 30 36
# Functions, R comes with many functions
# that you can use to do sophisticated
# tasks like random sampling
mean(die)
## [1] 3.5
round(mean(die))
## [1] 4
sample(x=die,size = 1)
## [1] 3
sample(x=die,size = 2)
## [1] 2 1
sample(x=die,size = 6)
## [1] 4 1 6 3 2 5
sample(die,size = 3)
## [1] 3 1 5
round(pi,digits = 5)
## [1] 3.14159
args(round)
## function (x, digits = 0)
## NULL
round(pi,digits =1)
## [1] 3.1
# Sample with Replacement
sample(die,size=2,replace = TRUE)
## [1] 4 4
dice <- sample(die,size = 2,replace = TRUE)
dice
## [1] 2 1
sum(dice)
## [1] 3
dice
## [1] 2 1
dice
## [1] 2 1
dice
## [1] 2 1
# Writing Your Own Functions
roll <- function(){
die <- 1:6
dice <- sample(die,size = 2,replace = TRUE)
sum(dice)
}
roll()
## [1] 10
# Arguments, You can supply bones when
# you call roll2 if you make bones
roll2 <-function(bones){
dice <- sample(bones,size = 2,replace = TRUE)
sum(dice)
}
roll2(2)
## [1] 3
roll2(4)
## [1] 3
roll2(1:6)
## [1] 11
roll()
## [1] 12
roll2(1:10)
## [1] 15
# You can prevent this error by giving
# the bones argument a default value.
# To do this, set bones equal to a
# value when you define roll3:
roll3 <-function(bones=1:6){
dice <- sample(bones,size = 2,replace = TRUE)
sum(dice)
}
roll3()
## [1] 7
# library
library(ggplot2)
# Let's take a look at a histogram to see
# if this makes sense. qplot will make a
# histogram whenever you give it only
# one vector to plot.
x3 <- c(0,1,1,2,2,2,3,3,4)
qplot(x3,binwidth=1)

# If you roll your dice many times and
# plot the results with qplot, the histogram
# will show you how often each sum appeared.
# The sums that occurred most often will
# have the highest bars
replicate(10,roll())
## [1] 6 4 6 9 7 5 8 8 4 11
# Patterns of long run frequencies will only
# appear over the long run. So let's simulate
# 10,000 dice rolls and plot the results
rolls <-replicate(1000,roll())
qplot(rolls,binwidth=1)

#help(sample)
#?sample()
# To weight your dice, you need to add
# a prob argument with a vector of weights
# to sample, like this:
roll4 <- function(){
die <- 1:6
dice <-sample(die,size = 2,replace = TRUE,
prob = c(1/8,1/8,1/8,1/8,1/8,3/8))
sum(dice)
}
roll4()
## [1] 3
rolls <- replicate(10000,roll4())
qplot(rolls,binwidth=1)

# Part II. Project 2: Playing Cards
# This project-which spans the next four
# chapters-will teach you how to store,
# retrieve, and change data values in your
# computer's memory.
# To keep the project simple, I've divided it
# into four tasks. Each task will teach you
# a new skill for managing data with R:
# Chapter 3. R Objects
# There is more than one way to build this matrix,
# but in every case, you will need to start by
# making a character vector with 10 values.
# If you start with the following character vector,
# you can turn it into a matrix with any of
# the following three commands:
hand1 <- c("ace","king","queen","jack",
"ten","spades","spades",
"spades","spades","spades")
matrix(hand1,nrow = 5)
## [,1] [,2]
## [1,] "ace" "spades"
## [2,] "king" "spades"
## [3,] "queen" "spades"
## [4,] "jack" "spades"
## [5,] "ten" "spades"
matrix(hand1,ncol=2)
## [,1] [,2]
## [1,] "ace" "spades"
## [2,] "king" "spades"
## [3,] "queen" "spades"
## [4,] "jack" "spades"
## [5,] "ten" "spades"
dim(hand1) <- c(5,2)
hand2 <- c("ace","spades","king","spades","queen","spades","jack","spades",
"ten","spades")
matrix(hand2,nrow = 5,byrow = TRUE)
## [,1] [,2]
## [1,] "ace" "spades"
## [2,] "king" "spades"
## [3,] "queen" "spades"
## [4,] "jack" "spades"
## [5,] "ten" "spades"
matrix(hand2,ncol = 2,byrow = TRUE)
## [,1] [,2]
## [1,] "ace" "spades"
## [2,] "king" "spades"
## [3,] "queen" "spades"
## [4,] "jack" "spades"
## [5,] "ten" "spades"
class(hand2)
## [1] "character"
# Dates and Times
now <- Sys.time()
now
## [1] "2016-02-18 07:23:45 VET"
# The time looks like a character string
# when you display it, but its data type
# is actually "double", and its class
# is "POSIXct" "POSIXt" (it has two classes):
class(now)
## [1] "POSIXct" "POSIXt"
# Loading Data
# You can load the deck data frame from
# the file deck.csv.
deck <- read.csv("C:\\Users\\Luis\\Desktop\\HandOnProgramming_R\\deck.csv",
header = TRUE,stringsAsFactors = FALSE)
deck[1:2,]
## face suit value
## 1 king spades 13
## 2 queen spades 12
x <- deck[1:2,1:2]
class(x)
## [1] "data.frame"
y <- deck[1:2,1]
y
## [1] "king" "queen"
class(y)
## [1] "character"
y <- deck[1:2,1,drop=FALSE]
y
## face
## 1 king
## 2 queen
class(y)
## [1] "data.frame"
deck[-1,1]
## [1] "queen" "jack" "ten" "nine" "eight" "seven" "six" "five"
## [9] "four" "three" "two" "ace" "king" "queen" "jack" "ten"
## [17] "nine" "eight" "seven" "six" "five" "four" "three" "two"
## [25] "ace" "king" "queen" "jack" "ten" "nine" "eight" "seven"
## [33] "six" "five" "four" "three" "two" "ace" "king" "queen"
## [41] "jack" "ten" "nine" "eight" "seven" "six" "five" "four"
## [49] "three" "two" "ace"
# Chapter 4. R Notation
# EXERCISE
# Complete the following code to make
# a function that returns the first
# row of a data frame:
# deal <- function(cards) {
# # ?
# }
# answer:
deal <- function(cards){
cards[1,]
}
deal(deck)#The function does exactly what
## face suit value
## 1 king spades 13
# you want: it deals the top card from
# your data set deal always returns the
# king of spades because deck doesn't know
# that we've dealt the card away
# Shuffle the Deck
# This may sound silly, but start by extracting
# every row in your data frame:
deck2 <- deck[1:52, ]
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
# What do you get? A new data frame whose order
# hasn't changed at all. What if you asked R
# to extract the rows in a different order?
# For example, you could ask for row 2,
# then row 1, and then the rest of the cards:
deck3 <- deck[c(2, 1, 3:52), ]
head(deck3)
## face suit value
## 2 queen spades 12
## 1 king spades 13
## 3 jack spades 11
## 4 ten spades 10
## 5 nine spades 9
## 6 eight spades 8
# R complies. You'll get all the rows back,
# and they'll come in the order you ask for
# them. If you want the rows to come in a
# random order, then you need to sort the
# integers from 1 to 52 into a random order
# and use the results as a row index.
# How could you generate such a random
# collection of integers? With our friendly
# neighborhood sample function:
random <- sample(1:52, size = 52)
random #Now the new set is truly shuffled.
## [1] 16 6 22 7 13 20 36 30 9 52 19 29 33 2 24 26 14 39 31 12 42 41 43
## [24] 8 50 48 44 40 32 11 3 38 34 17 51 25 45 21 37 23 47 4 15 18 28 1
## [47] 5 10 49 27 35 46
# You'll be finished once you wrap these
# steps into a function.
shuffle <- function(cards){
random <- sample(1:52,size = 52)
cards[random,]
}
shuffle(deck)
## face suit value
## 4 ten spades 10
## 2 queen spades 12
## 31 nine diamonds 9
## 25 two clubs 2
## 52 ace hearts 1
## 51 two hearts 2
## 26 ace clubs 1
## 20 seven clubs 7
## 45 eight hearts 8
## 19 eight clubs 8
## 9 five spades 5
## 40 king hearts 13
## 47 six hearts 6
## 28 queen diamonds 12
## 30 ten diamonds 10
## 48 five hearts 5
## 3 jack spades 11
## 27 king diamonds 13
## 32 eight diamonds 8
## 34 six diamonds 6
## 7 seven spades 7
## 24 three clubs 3
## 16 jack clubs 11
## 36 four diamonds 4
## 11 three spades 3
## 50 three hearts 3
## 35 five diamonds 5
## 17 ten clubs 10
## 46 seven hearts 7
## 43 ten hearts 10
## 49 four hearts 4
## 23 four clubs 4
## 33 seven diamonds 7
## 21 six clubs 6
## 18 nine clubs 9
## 37 three diamonds 3
## 14 king clubs 13
## 15 queen clubs 12
## 5 nine spades 9
## 39 ace diamonds 1
## 1 king spades 13
## 44 nine hearts 9
## 22 five clubs 5
## 10 four spades 4
## 13 ace spades 1
## 8 six spades 6
## 29 jack diamonds 11
## 12 two spades 2
## 42 jack hearts 11
## 41 queen hearts 12
## 38 two diamonds 2
## 6 eight spades 8
deck2 <-shuffle(deck)
deal(deck2)
## face suit value
## 38 two diamonds 2
deck_2 <- deck
# In the game of war, aces are king
# (figuratively speaking). They receive
# the highest value of all the cards,
# which would be something like 14.
# Every other card gets the value
# that it already has in deck.
# To play war, you just need to change
# the values of your aces from 1 to 14.
# As long as you haven't shuffled your deck,
# you know just where the aces are.
# They appear every 13 cards. Hence,
# you can describe them with R's notation system:
deck_2[c(13,26,39,52),]
## face suit value
## 13 ace spades 1
## 26 ace clubs 1
## 39 ace diamonds 1
## 52 ace hearts 1
deck_2$value[c(13,26,39,52)]
## [1] 1 1 1 1
deck_2$value[c(13,26,39,52)] <- 14
deck_2$value
## [1] 13 12 11 10 9 8 7 6 5 4 3 2 14 13 12 11 10 9 8 7 6 5 4
## [24] 3 2 14 13 12 11 10 9 8 7 6 5 4 3 2 14 13 12 11 10 9 8 7
## [47] 6 5 4 3 2 14
head(deck_2,13)
## 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
## 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 14
# But what if the deck had been shuffled?
# You could look through all the cards and
# note the locations of the aces, but that
# would be tedious. If your data frame were
# larger, it might be impossible:
deck_3 <- shuffle(deck)
head(deck_3)
## face suit value
## 23 four clubs 4
## 40 king hearts 13
## 31 nine diamonds 9
## 19 eight clubs 8
## 29 jack diamonds 11
## 25 two clubs 2
# Why not ask R to find the aces for you?
# You can do this with logical subsetting.
# Logical subsetting provides a way to do
# targeted extraction and modification with R
# objects, a sort of search-and-destroy
# mission inside your own data sets.
deck_2[,1]=="ace"
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [12] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [23] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [34] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
## [45] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
sum(deck_2[,1]=="ace")
## [1] 4
deck_2$face=="ace"
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [12] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [23] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [34] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
## [45] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
sum(deck_2=="ace")
## [1] 4
# You can use this method to spot and
# then change the aces in your deck-even
# if you've shuffled your cards.
# First, build a logical test that
# identifies the aces in your shuffled deck:
deck_3$face=="ace"
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE 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 TRUE FALSE FALSE FALSE FALSE FALSE
## [45] FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE
# Then use the test to single out
# the ace point values. Since the
# test returns a logical vector,
# you can use it as an index:
deck_3$value[deck_3$face=="ace"]
## [1] 1 1 1 1
#Finally, use assignment to change
#the ace values in deck3:
deck_3$value[deck_3$face == "ace"] <- 14
head(deck_3)
## face suit value
## 23 four clubs 4
## 40 king hearts 13
## 31 nine diamonds 9
## 19 eight clubs 8
## 29 jack diamonds 11
## 25 two clubs 2
# Let's put logical subsetting to use
# with a new game: hearts. In hearts,
# every card has a value of zero:
deck_4 <- deck
deck_4$value <- 0
deck_4
## face suit value
## 1 king spades 0
## 2 queen spades 0
## 3 jack spades 0
## 4 ten spades 0
## 5 nine spades 0
## 6 eight spades 0
## 7 seven spades 0
## 8 six spades 0
## 9 five spades 0
## 10 four spades 0
## 11 three spades 0
## 12 two spades 0
## 13 ace spades 0
## 14 king clubs 0
## 15 queen clubs 0
## 16 jack clubs 0
## 17 ten clubs 0
## 18 nine clubs 0
## 19 eight clubs 0
## 20 seven clubs 0
## 21 six clubs 0
## 22 five clubs 0
## 23 four clubs 0
## 24 three clubs 0
## 25 two clubs 0
## 26 ace clubs 0
## 27 king diamonds 0
## 28 queen diamonds 0
## 29 jack diamonds 0
## 30 ten diamonds 0
## 31 nine diamonds 0
## 32 eight diamonds 0
## 33 seven diamonds 0
## 34 six diamonds 0
## 35 five diamonds 0
## 36 four diamonds 0
## 37 three diamonds 0
## 38 two diamonds 0
## 39 ace diamonds 0
## 40 king hearts 0
## 41 queen hearts 0
## 42 jack hearts 0
## 43 ten hearts 0
## 44 nine hearts 0
## 45 eight hearts 0
## 46 seven hearts 0
## 47 six hearts 0
## 48 five hearts 0
## 49 four hearts 0
## 50 three hearts 0
## 51 two hearts 0
## 52 ace hearts 0
# except cards in the suit of
# hearts and the queen of spades.
# Each card in the suit of hearts
# has a value of 1
deck_4$suit=="hearts"
## [1] FALSE FALSE FALSE FALSE FALSE 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 TRUE TRUE TRUE TRUE
## [45] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
deck_4$value[deck_4$suit=="hearts"]
## [1] 0 0 0 0 0 0 0 0 0 0 0 0 0
deck_4$value[deck_4$suit=="hearts"] <- 1
deck_4$value[deck_4$suit=="hearts"]
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1
queenOfspades <- deck_4$face=="queen"&deck_4$suit=="spades"
deck_4[queenOfspades,]
## face suit value
## 2 queen spades 0
deck_4$value[queenOfspades]<- 13
deck_4[queenOfspades,]
## face suit value
## 2 queen spades 13
# Your deck is now ready to play hearts.
# Exercises
# Is w positive?
# Is x greater than 10 and less than 20?
# Is object y the word February?
# Is every value in z a day of the week?
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","Thrusday",
"Friday","Saturday","Sunday"))
## [1] TRUE
# Let's consider one last game, blackjack.
# In blackjack, each number card has
# a value equal to its face value.
# Each face card (king, queen, or jack)
# has a value of 10. Finally, each ace
# has a value of 11 or 1, depending on
# the final results of the game.
deck_5 <- deck
head(deck_5)
## 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
# You can change the value of the face cards
# in one fell swoop with %in%:
facecard <- deck_5$face %in% c("king","queen","jack")
deck_5$value[facecard] <- 10
deck_5
## 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 1
## 14 king clubs 10
## 15 queen clubs 10
## 16 jack clubs 10
## 17 ten clubs 10
## 18 nine clubs 9
## 19 eight clubs 8
## 20 seven clubs 7
## 21 six clubs 6
## 22 five clubs 5
## 23 four clubs 4
## 24 three clubs 3
## 25 two clubs 2
## 26 ace clubs 1
## 27 king diamonds 10
## 28 queen diamonds 10
## 29 jack diamonds 10
## 30 ten diamonds 10
## 31 nine diamonds 9
## 32 eight diamonds 8
## 33 seven diamonds 7
## 34 six diamonds 6
## 35 five diamonds 5
## 36 four diamonds 4
## 37 three diamonds 3
## 38 two diamonds 2
## 39 ace diamonds 1
## 40 king hearts 10
## 41 queen hearts 10
## 42 jack hearts 10
## 43 ten hearts 10
## 44 nine hearts 9
## 45 eight hearts 8
## 46 seven hearts 7
## 47 six hearts 6
## 48 five hearts 5
## 49 four hearts 4
## 50 three hearts 3
## 51 two hearts 2
## 52 ace hearts 1
deck_5$value[deck_5$face=="ace"]<- NA
deck_5
## 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
## 14 king clubs 10
## 15 queen clubs 10
## 16 jack clubs 10
## 17 ten clubs 10
## 18 nine clubs 9
## 19 eight clubs 8
## 20 seven clubs 7
## 21 six clubs 6
## 22 five clubs 5
## 23 four clubs 4
## 24 three clubs 3
## 25 two clubs 2
## 26 ace clubs NA
## 27 king diamonds 10
## 28 queen diamonds 10
## 29 jack diamonds 10
## 30 ten diamonds 10
## 31 nine diamonds 9
## 32 eight diamonds 8
## 33 seven diamonds 7
## 34 six diamonds 6
## 35 five diamonds 5
## 36 four diamonds 4
## 37 three diamonds 3
## 38 two diamonds 2
## 39 ace diamonds NA
## 40 king hearts 10
## 41 queen hearts 10
## 42 jack hearts 10
## 43 ten hearts 10
## 44 nine hearts 9
## 45 eight hearts 8
## 46 seven hearts 7
## 47 six hearts 6
## 48 five hearts 5
## 49 four hearts 4
## 50 three hearts 3
## 51 two hearts 2
## 52 ace hearts NA
# Congratulations. Your deck is now ready
# for a game of blackjack.Congratulations.
# Your deck is now ready for a game of blackjack.
library(pryr)
parenvs(all=TRUE)
## label name
## 1 <environment: R_GlobalEnv> ""
## 2 <environment: package:pryr> "package:pryr"
## 3 <environment: package:ggplot2> "package:ggplot2"
## 4 <environment: package:stats> "package:stats"
## 5 <environment: package:graphics> "package:graphics"
## 6 <environment: package:grDevices> "package:grDevices"
## 7 <environment: package:utils> "package:utils"
## 8 <environment: package:datasets> "package:datasets"
## 9 <environment: package:methods> "package:methods"
## 10 <environment: 0x04ec5828> "Autoloads"
## 11 <environment: base> ""
## 12 <environment: R_EmptyEnv> ""
ls(globalenv())
## [1] "deal" "deck" "deck_2" "deck_3"
## [5] "deck_4" "deck_5" "deck2" "deck3"
## [9] "dice" "die" "facecard" "hand1"
## [13] "hand2" "now" "queenOfspades" "random"
## [17] "roll" "roll2" "roll3" "roll4"
## [21] "rolls" "shuffle" "w" "x"
## [25] "x3" "y" "z"
environment()
## <environment: R_GlobalEnv>
foo <- "take me to your runtime"
show_env <- function(x = foo){
list(ran.in = environment(),
parent = parent.env(environment()),
objects = ls.str(environment()))
}
show_env(1:6)
## $ran.in
## <environment: 0x086ce710>
##
## $parent
## <environment: R_GlobalEnv>
##
## $objects
## x : int [1:6] 1 2 3 4 5 6
x <- c(1:6)
y <- 3
add<- function(){
exp(x*y)^2
}
add()
## [1] 4.034288e+02 1.627548e+05 6.565997e+07 2.648912e+10 1.068647e+13
## [6] 4.311232e+15
deal <- function(){
deck[1,]
}
environment(deal)
## <environment: R_GlobalEnv>
deal()
## face suit value
## 1 king spades 13
# You know enough R syntax to remove
# the top card of deck. The following
# code will save a pristine copy of deck
# and then remove the top card:
DECK <- deck
deck <- deck[-1,]
head(deck)
## face suit value
## 2 queen spades 12
## 3 jack spades 11
## 4 ten spades 10
## 5 nine spades 9
## 6 eight spades 8
## 7 seven spades 7
deal <- function(){
card <- deck[-1,]
deck <- deck[-1,]
card
}
deal()
## face suit value
## 3 jack spades 11
## 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 1
## 14 king clubs 13
## 15 queen clubs 12
## 16 jack clubs 11
## 17 ten clubs 10
## 18 nine clubs 9
## 19 eight clubs 8
## 20 seven clubs 7
## 21 six clubs 6
## 22 five clubs 5
## 23 four clubs 4
## 24 three clubs 3
## 25 two clubs 2
## 26 ace clubs 1
## 27 king diamonds 13
## 28 queen diamonds 12
## 29 jack diamonds 11
## 30 ten diamonds 10
## 31 nine diamonds 9
## 32 eight diamonds 8
## 33 seven diamonds 7
## 34 six diamonds 6
## 35 five diamonds 5
## 36 four diamonds 4
## 37 three diamonds 3
## 38 two diamonds 2
## 39 ace diamonds 1
## 40 king hearts 13
## 41 queen hearts 12
## 42 jack hearts 11
## 43 ten hearts 10
## 44 nine hearts 9
## 45 eight hearts 8
## 46 seven hearts 7
## 47 six hearts 6
## 48 five hearts 5
## 49 four hearts 4
## 50 three hearts 3
## 51 two hearts 2
## 52 ace hearts 1
# This code won't work because R will
# be in a runtime environment when it
# executes deck <- deck[-1, ]. Instead
# of overwriting the global copy of
# deck with deck[-1, ], deal will
# just create a slightly altered copy
# of deck in its runtime environment
# You can assign an object to a specific
# environment with the assign function:
deal <- function(){
card <- deck[1,]
assign("deck",deck[-1,],envir=globalenv())
card
}
deal()
## face suit value
## 2 queen spades 12
deal()
## face suit value
## 3 jack spades 11
#Let's turn our attention to the shuffle function:
# shuffle <- function(cards){
# random <- sample(1:52,size = 52)
# cards[random,]
# }
# shuffle(cards)
# head(deck)
a <- shuffle(deck)
head(deck)
## face suit value
## 4 ten spades 10
## 5 nine spades 9
## 6 eight spades 8
## 7 seven spades 7
## 8 six spades 6
## 9 five spades 5
head(a,3)
## face suit value
## 11 three spades 3
## 4 ten spades 10
## 34 six diamonds 6
# This behavior is now undesirable in two ways.
# First, shuffle fails to shuffle deck.
# Second, shuffle returns a copy of deck,
# which may be missing the cards that have
# been dealt away. It would be better if
# shuffle returned the dealt cards to
# the deck and then shuffled.
# This is what happens when you shuffle
# a deck of cards in real life.
shuffle <- function(){
random <- sample(1:52,size=52)
assign(deck,DECK[random,],envir = globalenv())
}
# Since DECK lives in the global environment,
# shuffle's environment of origin, shuffle
# will be able to find DECK at runtime.
# R will search for DECK first in shuffle's
# runtime environment, and then in shuffle's
# origin environment-the global environment-which
# # is where DECK is stored.
# The second line of shuffle will create a
# reordered copy of DECK and save it as deck
# in the global environment
# This willoverwrite the previous, nonshuffled
# version of deck.
ls(globalenv())
## [1] "a" "add" "deal" "deck"
## [5] "DECK" "deck_2" "deck_3" "deck_4"
## [9] "deck_5" "deck2" "deck3" "dice"
## [13] "die" "facecard" "foo" "hand1"
## [17] "hand2" "now" "queenOfspades" "random"
## [21] "roll" "roll2" "roll3" "roll4"
## [25] "rolls" "show_env" "shuffle" "w"
## [29] "x" "x3" "y" "z"
head(globalenv()$deck,3)
## face suit value
## 4 ten spades 10
## 5 nine spades 9
## 6 eight spades 8
assign("new","Hello Global",envir = globalenv())
globalenv()$new
## [1] "Hello Global"
new <- "Hello Active"
new
## [1] "Hello Active"
show_env <- function(){
list(ran.in=environment(),
parent=parent.env(environment()),
objects=ls.str(environment()))
}
show_env()
## $ran.in
## <environment: 0x050777fc>
##
## $parent
## <environment: R_GlobalEnv>
##
## $objects
# The results reveal that R created a new environment
# named 0x03e9e8f0 to run show_env() in.
# The environment had no objects in it,
# and its parent was the global environment.
show_env()
## $ran.in
## <environment: 0x0543a620>
##
## $parent
## <environment: R_GlobalEnv>
##
## $objects
# This time show_env ran in a new environment,
# 0x11476c48. R creates a new environment
# each time you run a function. The 0x11476c48
# environment looks exactly the same as 0x03e9e8f0 .
# It is empty and has the same global environment
# as its parent.
# Now let's consider which environment R will
# use as the parent of the runtime environment.
# R will connect a function's runtime environment
# to the environment that the function was first
# created in. This environment plays an important
# role in the function's life-because all of the
# function's runtime environments will use it
# as a parent. Let's call this environment
# the origin environment. You can look up a
# function's origin environment by running
# environment on the function:
environment(show_env)
## <environment: R_GlobalEnv>
# The origin environment of show_env is the
# global environment because we created
# show_env at the command line, but the origin
# environment does not need to be the
# global environment. For example, the environment
# of parenvs is the pryr package:
environment(parenvs)
## <environment: namespace:pryr>
# In other words, the parent of a runtime
# environment will not always be the global
# environment; it will be whichever environment
# the function was first created in.
# Finally, let's look at the objects contained
# in a runtime environment. At the moment,
# show_env's runtime environments do not
# contain any objects, but that is easy to fix.
# Just have show_env create some objects
# in its body of code. R will store any
# objects created by show_env in its runtime
# environment. Why? Because the runtime
# environment will be the active environment
# when those objects are created:
show_env <- function(){
a <- 1
b <- 2
c <- 3
list(ran.in=environment(),
objects=ls.str(environment()))
}
show_env()
## $ran.in
## <environment: 0x08a4be20>
##
## $objects
## a : num 1
## b : num 2
## c : num 3
# How can you use this knowledge to fix
# the deal and shuffle functions?
deal <- function(){
deck[1,]
}
environment(deal)
## <environment: R_GlobalEnv>
# When deal calls deck, R will need to
# look up the deck object. R's scoping
# rules will lead it to the version of
# deck in the global environment,
# as in Figure 6-5. deal works as
# expected as a result:
deal()
## face suit value
## 4 ten spades 10
# Now let's fix the deal function to remove
# the cards it has dealt from deck. Recall
# that deal returns the top card of deck but
# does not remove the card from the deck.
# As a result, deal always returns the same card:
deal()
## face suit value
## 4 ten spades 10
# You know enough R syntax to remove the top card
# of deck. The following code will save a pristine
# copy of deck and then remove the top card:
DECK <- deck
deck <- deck[-1,]
head(deck,3)
## face suit value
## 5 nine spades 9
## 6 eight spades 8
## 7 seven spades 7
# Now let's add the code to deal. Here deal saves
# (and then returns) the top card of deck.
# In between, it removes the card from
# deck.or does it?
deal <- function(){
card <- deck[1,]
deck <- deck[-1,]
card
}
deal()
## face suit value
## 5 nine spades 9
deal()
## face suit value
## 5 nine spades 9
# This code won't work because R will be in a
# runtime environment when it executes
# deck <- deck[-1, ]. Instead of overwriting
# the global copy of deck with deck[-1, ], deal
# will just create a slightly altered copy of
# deck in its runtime environment,
# You can assign an object to a specific environment
# with the assign function:
deal <- function(){
card <- deck[1,]
assign("deck",deck[-1,],envir = globalenv())
card
}
# Now deal will finally clean up the global
# copy of deck, and we can deal cards just
# as we would in real life:
deal()
## face suit value
## 5 nine spades 9
deal()
## face suit value
## 6 eight spades 8
#Let's turn our attention to the shuffle function:
shuffle <- function(cards){
random <- sample(1:52,size = 52)
cards[random,]
}
# shuffle(deck) doesn't shuffle the deck object;
# it returns a shuffled copy of the deck object:
a <- shuffle(deck)
head(deck,3)
## face suit value
## 7 seven spades 7
## 8 six spades 6
## 9 five spades 5
head(a,3)
## face suit value
## 45 eight hearts 8
## 37 three diamonds 3
## 11 three spades 3
# This behavior is now undesirable in two ways.
# First, shuffle fails to shuffle deck.
# Second, shuffle returns a copy of deck,
# which may be missing the cards that have
# been dealt away. It would be better if
# shuffle returned the dealt cards to the
# deck and then shuffled. This is what
# happens when you shuffle a deck of
# cards in real life.
# You can update shuffle in the same way that
# you updated deck. The following version will
# do the job:
shuffle <- function(){
random <- sample(1:52,size = 52)
assign("deck",DECK[random,],envir = globalenv())
}
# Since DECK lives in the global environment,
# shuffle's environment of origin, shuffle
# will be able to find DECK at runtime.
# R will search for DECK first in shuffle's
# runtime environment, and then in shuffle's
# origin environment-the global environment-which
# is where DECK is stored.
# The second line of shuffle will create a
# reordered copy of DECK and save it as deck
# in the global environment. This will overwrite
# the previous, nonshuffled version of deck.
# Our system finally works. For example,
# you can shuffle the cards and then deal
# a hand of blackjack:
shuffle()
deal()
## face suit value
## 4 ten spades 10
deal()
## face suit value
## 7 seven spades 7
# Closures
# But the system requires deck and DECK to
# exist in the global environment. Lots of
# things happen in this environment, and
# it is possible that deck may get modified
# or erased by accident.
# It would be better if we could store deck
# in a safe, out-of-the-way place, like one
# of those safe, out-of-the-way environments
# that R creates to run functions in. In fact,
# storing deck in a runtime environment
# is not such a bad idea.
# You could create a function that takes deck
# as an argument and
# saves a copy of deck as DECK. The function
# could also save its own copies of deal and shuffle:
setup <- function(deck){
DECK <- deck
DEAL <- function(){
card <- deck[-1,]
assign("deck",deck[-1],envir = globalenv())
card
}
SHUFFLE <- function(){
random <- sample(1:52,size = 52)
assign("deck",DECK[random,],envir = globalenv())
}
}
# When you run setup, R will create a runtime
# environment to store these objects in.
# The environment will look like Figure 6-7.
# Now all of these things are safely out of
# the way in a child of the global environment.
# That makes them safe but hard to use.
# Let's ask setup to return DEAL and SHUFFLE
# so we can use them. The best way to do this
# is to return the functions as a list
setup <- function(deck){
DECK <- deck
DEAL <- function(){
card <- deck[-1,]
assign("deck",deck[-1],envir = globalenv())
card
}
SHUFFLE <- function(){
random <- sample(1:52,size = 52)
assign("deck",DECK[random,],envir = globalenv())
}
list(deal=DEAL,shuffle=SHUFFLE)
}
cards <- setup(deck)
# Then you can save each of the elements of
# the list to a dedicated object in
# the global environment:
deal <- cards$deal
shuffle <- cards$shuffle
# Now you can run deal and shuffle just as before.
# Each object contains the same code as the
# original deal and shuffle
deal
## function(){
## card <- deck[-1,]
## assign("deck",deck[-1],envir = globalenv())
## card
## }
## <environment: 0x083efbbc>
shuffle
## function(){
## random <- sample(1:52,size = 52)
## assign("deck",DECK[random,],envir = globalenv())
## }
## <environment: 0x083efbbc>
# However, the functions now have one important
# difference. Their origin environment is no
# longer the global environment (although deal
# and shuffle are currently saved there).
# Their origin environment is the runtime
# environment that R made when you ran setup.
# That's where R created DEAL and SHUFFLE,
# the functions copied into the new deal
# and shuffle, as shown in:
environment(deal)
## <environment: 0x083efbbc>
environment(shuffle)
## <environment: 0x083efbbc>
# Why does this matter? Because now when you run
# deal or shuffle, R will evaluate the functions
# in a runtime environment that uses 0x7ff7169c3390
# as its parent. DECK and deck will be in this
# parent environment, which means that deal and
# shuffle will be able to find them at runtime.
# DECK and deck will be in the functions' search
# path but still out of the way in every other
# respect
# This arrangement is called a closure.
# setup's runtime environment "encloses"
# the deal and shuffle functions. Both deal
# and shuffle can work closely with the
# objects contained
# in the enclosing environment, but almost
# nothing else can. The enclosing environment
# is not on the search path for any other
# R function or environment.
# You may have noticed that deal and shuffle
# still update the deck object in the global
# environment. Don't worry, we're about to change that.
# We want deal and shuffle to work exclusively
# with the objects in the parent (enclosing)
# environment of their runtime environments.
# Instead of having each function reference
# the global environment to update deck,
# you can have them reference their parent
# environment at runtime,
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,1],envir = parent.env(environment()))
}
list(deal=DEAL,shuffle=SHUFFLE)
}
cards <- setup(deck)
deal <- cards$deal
deck <- cards$shuffle
# We finally have a self-contained card game.
# You can delete (or modify) the global copy
# of deck as much as you want and still play
# cards. deal and shuffle will use the pristine,
# protected copy deck
rm(deck)
shuffle()
deal()
## face suit value
## 6 eight spades 8
deal()
## face suit value
## NA <NA> <NA> NA
# Summary
# R saves its objects in an environment system
# that resembles your computer's file system.
# If you understand this system, you can predict
# how R will look up objects. If you call an
# object at the command line, R will look for
# the object in the global environment and then
# the parents of the global environment, working
# its way up the environment tree one
# environment at a time.
# R will use a slightly different search
# path when you call an
# object from inside of a function. When you
# run a function, R creates a new environment
# to execute commands in. This environment will
# be a child of the environment where the
# function was originally defined. This may
# be the global environment, but it also may
# not be. You can use this behavior
# to create closures, which are functions
# linked to objects in protected environments.
# As you become familiar with R's environment
# system, you can use it to produce elegant
# results, like we did here. However,
# the real value of understanding the
# environment system comes from knowing
# how R functions do their job. You can
# use this knowledge to figure out what is
# going wrong when a function does not
# perform as expected.