In Place Modification of Matrices in R

In place modification of matrices in R

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)

How to assign row changes to an existing matrix within an 'apply' function from the parallel package

You can't assign in parallel, as you're just assigning to a local copy of the matrix.

Two solutions:

  1. Use shared memory (e.g. matrices on disk using package {bigstatsr}; disclaimer: I'm the author)

  2. Don't assign in the first place. Just run the lapply(), get all the results parts as a list and use do.call("rbind", list).

Modifying an element in a list of matrices

I would just do a for loop, easy and clear:

for(i in seq_along(AA)) {
AA[[i]][1, 3] = AA[[i]][1, 3] * i / length(AA)
}

Function to return modified matrix in R

The assignment is happening within the function's environment, not the global one. You need to return the result in the function, and assign it with the function call. Try this:

addfunction <- function(x){
x$XTSSum2 <- x$XTS1 + lag(x$XTS1,1)
x
}
XTS1 <- addfunction(XTS1)

Modifying an matrix surrounding elements of an element?

You are checking if the value is 2 and not 1 like it is in your example the y[row,col] == 2. This needs to be changed to y[row,col] == 1 if you want the example in the question to work correctly.

You can also add if statements to check if the position you want to change is out of bounds.

y <- mat
for(row in 1:nrow(y)){
for(col in 1:ncol(y)){
if(y[row,col] == 1){
if(row > 1){
if(col > 1){
y[row-1,col] <- sample(c(0,1), replace = TRUE, size = 1)
y[row,col-1] <- sample(c(0,1), replace = TRUE, size = 1)
y[row-1,col-1] <- sample(c(0,1), replace = TRUE, size = 1)
}
if(col < ncol(y)){
y[row-1,col+1] <- sample(c(0,1), replace = TRUE, size = 1)
y[row,col+1] <- sample(c(0,1), replace = TRUE, size = 1)
}
}
if(row < nrow(y)){
if(col > 1){
y[row+1,col] <- sample(c(0,1), replace = TRUE, size = 1)
y[row+1,col-1] <- sample(c(0,1), replace = TRUE, size = 1)
}
if(col < ncol(y)){
y[row+1,col+1] <- sample(c(0,1), replace = TRUE, size = 1)
}
}
}
}
}

In R how would you replace values in a matrix that have a certain condition with values from another vector?

Thought you had to use apply(Matrix, \(x) pmin(x, Vector)), but actually, you can just use pmin() directly on your Matrix because it will recycle the Vector to match the length.

pmin(Matrix, Vector)
#> [,1] [,2]
#> [1,] 2 2
#> [2,] 3 3
#> [3,] 3 2
#> [4,] 1 1

Does R copy an entire matrix while modifying?

It seems the object does not get copied in this case. You can use the base::tracemem() function:

mat <- matrix(7,10,10)
mat_filter <- cbind(c(1,6,10),
c(1,5,3))

tracemem(mat)
[1] "<0x7fa68bfde840>"

This returns the current memory address of mat, and will print any change in address, if one occurs.

mat[mat_filter] <- mat[mat_filter] + 1

produces no tracemem output, so the modification should be happening in place.

Hadley Wickham's Advanced R has a chapter on this.

Change elements in one matrix based on positions given by another matrix in R

You want to do something like matrix subsetting (e.g., P[Q]) except that you can't use negative indexing in matrix subsetting (e.g., P[-Q] is not allowed). Here's a work-around.

Store the elements you want to retain from A in a 2-column matrix where each row is a coordinate of A:

Idx <- cbind(rep(1:4, each=ncol(B)), as.vector(t(B)))

Create a matrix where all values are Inf, and then overwrite the values you wanted to "keep" from A:

Res <- matrix(Inf, nrow=nrow(A), ncol=ncol(A))
Res[Idx] <- A[Idx]

Result

Res
# [,1] [,2] [,3] [,4]
#[1,] 0.9043131 0.639718071 Inf 0.19158238
#[2,] 0.6397181 0.601327568 0.007363378 Inf
#[3,] Inf 0.007363378 0.752123162 0.61428003
#[4,] 0.1915824 Inf 0.614280026 0.02932679

Manipulation List of Matrices in R

Try

lapply(L, function(x) diag(rowSums(x))-x)

data

set.seed(25)
L <- lapply(1:5, function(i) matrix(sample(1:20, 4*4,
replace=TRUE), ncol=4))


Related Topics



Leave a reply



Submit