13

I there any way to avoid copy-on-modify for in-place modifications of matrices in R?

I am trying to copy a smaller matrix to a slice of larger matrix as follows.

library(data.table)
y <- matrix(c(11,21,31,12,22,32),nrow=3,ncol=2)
address(y)
[1] "08429190"

y[2:3,] <- matrix(c(1,1,8,12),nrow=2)
address(y)
[1] "0E033D28"
Crops
  • 5,024
  • 5
  • 38
  • 65
  • 2
    that returns the same address on my comp (and with prefix "0x"). – Rorschach Jun 21 '15 at 19:32
  • 3
    When I try the above commands using `address` from the data.table package or from the pryr package I get the same address for the two instances above. Suggest you try a newer version of R. Also please provide self contained code samples including library calls. – G. Grothendieck Jun 21 '15 at 19:32
  • 3
    Using `data.table::address`, I get the same behavior as OP. (R 3.2.0 , RStudio 0.99.441, Windows 8.0,data.table 1,9,5). But, with R console, I it returns the same address. So, the problem is with RStudio. – user227710 Jun 21 '15 at 19:49

1 Answers1

10

I get the same behaviour as the OP using R 3.2.0 running within RStudio 0.99.441 on Windows 8.1 and using pryr::address. The issue is RStudio has a reference to y for its Environment pane. As often the case, Hadley Wickham has some excellent documentation of this.

I don't think there's any way around this for matrices in the global environment other than not using RStudio. I've tried a couple of other things. Matrices within a function are fine:

library("pryr")
fn <- function() {
  y <- matrix(c(11,21,31,12,22,32),nrow=3,ncol=2)
  print(address(y))
  y[2:3,] <- matrix(c(1,1,8,12),nrow=2)
  print(address(y))
}

Calling fn() should show that the address is unchanged.

However, creating y as a member of a list or environment which are in the global environment doesn't prevent the copy on write (e.g. x <- new.env(); x$y <- matrix(...)).

Per Is there any way to disable environment pane in RStudio? there doesn't seem to be any way of disabling the environment pane.

data.table still manages to avoid unncessarily copies. Try:

library("data.table")
x <- as.data.table(matrix(c(11,21,31,12,22,32),nrow=3,ncol=2))
address(x)
x[2:3, `:=`(V1 = c(1, 1), V2 = c(8, 12))]
address(x)
x[, V3 := V1 + V2]
address(x)
Community
  • 1
  • 1
Nick Kennedy
  • 12,510
  • 2
  • 30
  • 52