Section 2.2: distinction between names and values
Section 2.3: describes when R makes a copy
Section 2.2: distinction between names and values
Section 2.3: describes when R makes a copy
Section 2.4: explores how much memory an object occupies
Section 2.2: distinction between names and values
Section 2.3: describes when R makes a copy
Section 2.4: explores how much memory an object occupies
Section 2.5: describes the two important exceptions to copy-on-modify
Section 2.2: distinction between names and values
Section 2.3: describes when R makes a copy
Section 2.4: explores how much memory an object occupies
Section 2.5: describes the two important exceptions to copy-on-modify
Section 2.6: concludes the chapter with a discussion of the garbage collector
Section 2.2: distinction between names and values
Section 2.3: describes when R makes a copy
Section 2.4: explores how much memory an object occupies
Section 2.5: describes the two important exceptions to copy-on-modify
Section 2.6: concludes the chapter with a discussion of the garbage collector
Prerequisites
To understand how R represents objects, we'll need to install the lobstr package:
library(lobstr)# We also install emo because it's fun!# devtools::install_github("hadley/emo")
How would you read the following?
x <- c(1, 2, 3)
How would you read the following?
x <- c(1, 2, 3)
How would you read the following?
x <- c(1, 2, 3)
Create an object named ‘x’, containing the values 1, 2, and 3: 💩
It’s creating an object, a vector of values (1, 2, 3) and it’s binding that object to a name, x : 😄
x <- c(1, 2, 3)
x
## [1] 1 2 3
How can we see what's happening under the hood?
x <- c(1, 2, 3)
x
## [1] 1 2 3
How can we see what's happening under the hood?
You can call obj_address()
to see this object's identifier:
obj_addr(x)
## [1] "0x125d01a8"
x <- c(1, 2, 3)
x
## [1] 1 2 3
How can we see what's happening under the hood?
You can call obj_address()
to see this object's identifier:
obj_addr(x)
## [1] "0x125d01a8"
y <- x
x <- c(1, 2, 3)
x
## [1] 1 2 3
How can we see what's happening under the hood?
You can call obj_address()
to see this object's identifier:
obj_addr(x)
## [1] "0x125d01a8"
y <- x
obj_addr(y)
## [1] "0x125d01a8"
x
when you modify y
?y[[3]] <- 4
x
when you modify y
?y[[3]] <- 4
x
## [1] 1 2 3
x
when you modify y
?y[[3]] <- 4
x
## [1] 1 2 3
y
did not modify x
. x
when you modify y
?y[[3]] <- 4
x
## [1] 1 2 3
y
did not modify x
. x
when you modify y
?y[[3]] <- 4
x
## [1] 1 2 3
y
did not modify x
. obj_addr(x)
## [1] "0x125d01a8"
obj_addr(y)
## [1] "0x13293038"
The same copy-on-modify behavior applies for functions.
The same copy-on-modify behavior applies for functions.
We can use tracemem()
to track when an object gets copied. It allows us to do that because every time an object gets copied, a message containing the address of the object will be printed.
The same copy-on-modify behavior applies for functions.
We can use tracemem()
to track when an object gets copied. It allows us to do that because every time an object gets copied, a message containing the address of the object will be printed.
f <- function(a) { a}
x <- c(1, 2, 3)cat(tracemem(x), "\n")
## <000000001E0C8120>
The same copy-on-modify behavior applies for functions.
We can use tracemem()
to track when an object gets copied. It allows us to do that because every time an object gets copied, a message containing the address of the object will be printed.
f <- function(a) { a}
x <- c(1, 2, 3)cat(tracemem(x), "\n")
## <000000001E0C8120>
z <- f(x)
We got no message here, which means no new copy was generated.
The same copy-on-modify behavior applies for functions.
We can use tracemem()
to track when an object gets copied. It allows us to do that because every time an object gets copied, a message containing the address of the object will be printed.
f <- function(a) { a}
x <- c(1, 2, 3)cat(tracemem(x), "\n")
## <000000001E0C8120>
z <- f(x)
We got no message here, which means no new copy was generated.
If f did modify x, then a new copy would get generated and thus a message would get printed by tracemem()
.
Like vectors, lists also use copy-on-modify behaviour.
Like vectors, lists also use copy-on-modify behaviour.
list_1 <- list(1, 2, 3)
list_2 <- list_1
Like vectors, lists also use copy-on-modify behaviour.
list_1 <- list(1, 2, 3)
list_2 <- list_1
obj_addr(list_1)
## [1] "0x121f6fc0"
obj_addr(list_2)
## [1] "0x121f6fc0"
Like vectors, lists also use copy-on-modify behaviour.
list_1 <- list(1, 2, 3)
list_2 <- list_1
obj_addr(list_1)
## [1] "0x121f6fc0"
obj_addr(list_2)
## [1] "0x121f6fc0"
list_2[[3]] <- 4
obj_addr(list_2)
## [1] "0x1e482598"
We can use lobstr::ref()
to print the memory address of each object along with a local ID so that we can easily cross-reference shared components.
We can use lobstr::ref()
to print the memory address of each object along with a local ID so that we can easily cross-reference shared components.
ref(list_1, list_2)
## o [1:0x121f6fc0] <list> ## +-[2:0x1db8e278] <dbl> ## +-[3:0x1db8e240] <dbl> ## \-[4:0x1db8e208] <dbl> ## ## o [5:0x1e482598] <list> ## +-[2:0x1db8e278] ## +-[3:0x1db8e240] ## \-[6:0x1e289378] <dbl>
This shows that list_1
and list_2
have shared components, namely integers 2 and 3 corresponding to the 2nd and 3rd element in their vectors.
Data frames are lists of vectors.
Data frames are lists of vectors.
If you modify a column:
only that column needs to be modified
the others will still point to their original references:
If you modify a row:
every column is modified
every column must be copied:
Consider this character vector:
x <- c("marco", "polo", "marco", "polo")
ref(x, character = T)
## o [1:0x13428ae0] <chr> ## +-[2:0x137efa98] <string: "marco"> ## +-[3:0x137ef9f0] <string: "polo"> ## +-[2:0x137efa98] ## \-[3:0x137ef9f0]
This is called a global string pool where each element of a character vector is a pointer to a unique string in the pool. This has implications for how much memory a character vector uses. To find out, use lobstr::obj_size()
Modyfing an R object usually creates a copy. Exceptions:
Modyfing an R object usually creates a copy. Exceptions:
Modyfing an R object usually creates a copy. Exceptions:
Implication: create functions that “remember” their previous state (more on this in Chapter 16)
gc()
yourself unless you want to:Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |