Evaluate custom expression in R - r

I need to assign a matrix to a custom designed variable in R. So here is the matrix:
A = matrix(c(2,4,3,1,7,5),nrow=2,ncol=3,byrow=TRUE)
and here is the custom designed variable name:
G <- "Pakka"
Here I create the expression now:
G <- paste(G, "<- A")
and now I need to evaluate the expression so that the matrix A is assigned to the variable named Pakka.
eval(parse(G))
However, there is an error given by R saying
Not able to open file name `Pakka <- A`. No file of that name found.
Searing on environment is not giving me any clues. Please help!

The eval(parse(G)) in the above question, has to be replaced by eval(parse(text=G)).
This will solve the problem.

You should really use eval(call()) for this, or delayedAssign.
Using eval(call()) :
"<-" is a special type of function, so we can hold it as an unevaluated call. Then when we're ready to evaluate it, we just wrap it with eval. This was how this type of assignment was designed.
> A <- matrix(c(2,4,3,1,7,5),nrow=2,ncol=3,byrow=TRUE)
> G <- "Pakka"
> e <- call("<-", as.name(G), substitute(A))
A look at e shows that it's exactly what we want to do.
> e
# Pakka <- A
Now we evaluate it, and Pakka is assigned to A.
> eval(e)
> Pakka
# [,1] [,2] [,3]
#[1,] 2 4 3
#[2,] 1 7 5
> A <- matrix(c(2,4,3,1,7,5),nrow=2,ncol=3,byrow=TRUE)
Using delayedAssign we can create a promise (unevaluated object) :
> delayedAssign("Pakka", A)
> ls()
[1] "A" "Pakka" ## Pakka is there, but not in memory yet
> Pakka
# [,1] [,2] [,3]
#[1,] 2 4 3
#[2,] 1 7 5

Related

Two errors in writing R code of QR decomposition using Gram-Schmidtand method and want to know why it went wrong

I write code manually of QR decomposition using Gram-Schmidt orthogonalization:
A<-cbind(c(2,-2,18),c(2,1,0),c(1,2,0),c(2,3,4))
gsm<-function(X){
m<-ncol(X)
n<-nrow(X)
# initialize Q and R
q<-matrix(0,m,n)
r<-matrix(0,n,n)
v<-matrix(0,m,n)
# initialize V
v[,1]<-X[,1]
q[,1]<-v[,1]/sqrt(sum(v[,1]^2))
r[1,1]<-t(X[,1])%*%q[,1]
for (i in 2:n){
dv<-0
for (j in 1:(i-1)) {
r[j,i]<-t(X[,i])%*%q[,j]
dv<-dv+r[j,i]*q[,j]
}
v[,i]<-X[,i]-dv
q[,i]<-v[,i]/sqrt(t(v[,i])%*%v[,i])
r[i,i]<-t(X[,i])%*%q[,i]
}
qrreport<-list("Q"=q,"R"=r)
return(qrreport)
}
gsm(A)
However, the code doesn't work and gives me the error:
Error in v[, 1] <- X[, 1] : number of items to replace is not a multiple of replacement length
And when I replace A with a 3*3 matrix: A<-cbind(c(2,-2,18),c(2,1,0),c(1,2,0)) and operate the function again, R throws a new error to me as:
Recycling array of length 1 in vector-array arithmetic is deprecated.
Use c() or as.vector() instead.
Recycling array of length 1 in vector-array arithmetic is deprecated.
Use c() or as.vector() instead.
$ Q
[,1] [,2] [,3]
[1,] 0.1097643 0.89011215 -0.4423259
[2,] -0.1097643 0.45314800 0.8846517
[3,] 0.9878783 -0.04855157 0.1474420
$R
[,1] [,2] [,3]
[1,] 18.22087 0.1097643 -0.1097643
[2,] 0.00000 2.2333723 1.7964082
[3,] 0.00000 0.0000000 1.3269776
I am very confused where I make mistakes and hope someone could help me debug.
Your A matrix has 3 rows and 4 columns, so in gsm() m is 4 and n is 3. That means v has 4 rows and 3 columns, whereas X, which is really A, only has 3 rows. When v[, 1] <- X[, 1] tries to put the 1st column of X into the first
column of A, you get the error message you saw.
To debug things like this in RStudio, set a breakpoint on the line v[, 1] <- X[, 1] that caused the error, and look at the different items in the expression before executing it. If you're not using RStudio, you can still set a breakpoint there using the setBreakpoint function, but it's a lot more work.

R programming:How to use loop on variables labelled in a consecutive manner?

I'm trying to figure out, how I can run a loop on some variables that have a consecutive label.
I want to do matrix.2-Matrix.1 and store it in matrix x.1, then Matrix.3-matrix.2 and store it in matrix x.2. There are 300 matrices(Matrix.1,Matrix.2,...Matrix.300) but for this example, I would like to just work on matrix 1,2 and 3.
I first tried an approach that involved the list function, but it didn't work, and then I thought about using a MACRO just like in SAS (the % symbol). But the Macro approach seemed not to work in R.
My code is below:
(The list approach)
> Matrix.1=matrix(c(1:6),nrow=2,ncol=3,byrow=TRUE)
> Matrix.2=matrix(c(1,8,9,17,15,2),nrow=2,ncol=3,byrow=TRUE)
> Matrix.3=matrix(c(0,1,2,3,6,0),nrow=2,ncol=3,byrow=TRUE)
> x.1=matrix(rep(0,6),nrow=2,ncol=3,byrow=TRUE)
> x.2=matrix(rep(0,6),nrow=2,ncol=3,byrow=TRUE)
> m=list(Matrix.1=Matrix.1,Matrix.2=Matrix.2,Matrix.3=Matrix.3)
> x=list(x.1=x.1,x.2=x.2)
> m[1]
$Matrix.1
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
> m[2]
$Matrix.2
[,1] [,2] [,3]
[1,] 1 8 9
[2,] 17 15 2
> m[3]
$Matrix.3
[,1] [,2] [,3]
[1,] 0 1 2
[2,] 3 6 0
> x[1]
$x.1
[,1] [,2] [,3]
[1,] 0 0 0
[2,] 0 0 0
> x[2]
$x.2
[,1] [,2] [,3]
[1,] 0 0 0
[2,] 0 0 0
> for (i in 1:2){
+ x[i]=m[i+1]-m[i]
+ print(x[i])
+ }
Error in m[i + 1] - m[i] : non-numeric argument to binary operator
>
How can I make operations on list?
> #Other approach inspired from SAS
> for (i in i:2){
+ x.i=Matrix.i+1-Matrix.i
+ print(R.i)
+ }
Error: object 'Matrix.i' not found
This second approach isn't even doable in R.
What is the best way of dealing loops involving consecutively labelled variables?
Since m and x are both lists, you need to use m[[1]] and x[[1]] to extract its elements.
for (i in 1:2){
x[[i]] <- m[[i+1]]-m[[i]]
print(x[[i]])
}
On the other hand, if you have 300 matrices (Matrix.1, Matrix.2, ... Matrix.300), you could use get and assign to deal with the numerical labels. Here I first assign values to 300 matrices with names Matrix.1 through Matrix.300. Then I use get function to extract these matrices and generate list x.
for (i in 1:300) {
assign(paste("Matrix.", i, sep = ""), matrix(rnorm(9), 3, 3))
}
x <- list()
for (i in 2:300) {
x[[i-1]] <- get(paste("Matrix.", i, sep = "")) - get(paste("Matrix.", i-1, sep = ""))
}
It is the preferred method in R to use the apply family of functions to loop through objects. For lists, you can use lapply which returns a list, or sapply which returns the most simplified object it can without losing any information. With these functions, you output is stored in the same order as the input, which makes comparisons or additional steps much easier.
myProcessedList <- lapply(x, FUN=<some function>)
This is a lot simpler and more straightforward than using assign and get and is worth the investment to learn. SO has many useful examples.

How can I make processing of matrices and vectors regular (as, e.g., in Matlab)

Suppose I have a function that takes an argument x of dimension 1 or 2. I'd like to do something like
x[1, i]
regardless of whether I got a vector or a matrix (or a table of one variable, or two).
For example:
x = 1:5
x[1,2] # this won't work...
Of course I can check to see which class was given as an argument, or force the argument to be a matrix, but I'd rather not do that. In Matlab, for example, vectors are matrices with all but one dimension of size 1 (and can be treated as either row or column, etc.). This makes code nice and regular.
Also, does anyone have an idea why in R vectors (or in general one dimensional objects) aren't special cases of matrices (or multidimensional objects)?
Thanks
In R, it is the other way round; matrices are vectors. The matrix-like behaviour comes from some extra attributes on top of the atomic vector part of the object.
To get the behaviour you want, you'd need to make the vector be a matrix, by setting dimensions on the vector using dim() or explicit coercion.
> vm <- 1:5
> dim(vm) <- c(1,5)
> vm
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
> class(vm)
[1] "matrix"
Next you'll need to maintain the dimensions when subsetting; by default R will drop empty dimensions, which in the case of vm above is the row dimension. You do that using drop = FALSE in the call to '['(). The behaviour by default is drop = TRUE:
> vm[, 2:4]
[1] 2 3 4
> vm[, 2:4, drop = FALSE]
[,1] [,2] [,3]
[1,] 2 3 4
You could add a class to your matrices and write methods for [ for that class where the argument drop is set to FALSE by default
class(vm) <- c("foo", class(vm))
`[.foo` <- function(x, i, j, ..., drop = FALSE) {
clx <- class(x)
class(x) <- clx[clx != "foo"]
x[i, j, ..., drop = drop]
}
which in use gives:
> vm[, 2:4]
[,1] [,2] [,3]
[1,] 2 3 4
i.e. maintains the empty dimension.
Making this fool-proof and pervasive will require a lot more effort but the above will get you started.

Object reassignment inside functions in R

Slightly embarrassed to ask such a simple question but I've wasted an hour now and figure its a 30 second solution. The problem is how to edit an existing object that is provided as an input to a function. I've also played with the super-assignment <<- without success.
The example function uses 2 inputs (one for an object and one for its name). I just need a form of this that removes the need for the 'n' input.
m <- c(2,5,3,7,1,3,9,3,5)
dim(m) <- c(3,3)
m
f <- function(x, n) { # where 'n' is the object name of 'x'
x[1,] <- c(1,2,3)
assign(n, x, envir = .GlobalEnv)
}
f(m, 'm')
m
Thanks in advance.
OK solved. Thanks #Andrie, sorry I misunderstood your reply.
Rookie error :(
f <- function(x) {
x[1,] <- c(1,2,3)
return(x)
}
m <- f(m)
m
You don't need to provide the name as an extra argument; substitute will get that for you. To do things in the scope of the calling function you use eval with parent.frame.
f <- function(x) {
eval(substitute( x[1,] <- c(1,2,3) ), parent.frame())
}
Then,
m <- c(2,5,3,7,1,3,9,3,5)
> dim(m) <- c(3,3)
> m
[,1] [,2] [,3]
[1,] 2 7 9
[2,] 5 1 3
[3,] 3 3 5
> f(m)
> m
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 5 1 3
[3,] 3 3 5
That said, modifying the caller's environment is generally a bad idea and it will usually lead to less confusing/fragile code if you just return the value and re-assign it to m instead. This is generally preferable.:
f <- function (x) {
x[1,] <- c(1,2,3)
x
}
m <- f(m)
However, I have occasionally found eval shenanigans to come in handy when I really needed to change an array in place and avoid an array copy.
I am probably missing the point of why you want to do this, but this will do exactly what you want, I think:
m[1,] = c(1,2,3)
The value of m has been changed in the global environment.
I'm just guessing here, but often folks who are writing functions to take the "names" of objects find that R lists can be useful. If you find yourself wanting to manipulate variables based on names, consider using R lists instead. Remember that every member of a list can have a different data type if necessary.

In R: How to perform log on elements of a matrix without a loop

In R: How do I perform a log operation on every element of a matrix without using a loop?
I have a matrix m and I want each element to be replaced by its log.
log(m) doesn't work.
params = array(list(),c(2, 2))
then I manually set all elements.
params
[,1] [,2]
[1,] 3 3
[2,] 3 3
log(params)
Error in log(params) : Non-numeric argument to mathematical function
log(M) works for all of us on correct matrices:
R> M <- matrix(1:4,2)
R> M
[,1] [,2]
[1,] 1 3
[2,] 2 4
R> log(M)
[,1] [,2]
[1,] 0.00000 1.0986
[2,] 0.69315 1.3863
R>
Can you show us your M ?
You failed at making matrix -- this way you have a matrix of lists, and you want a matrix of numbers.
Try this:
params<-array(3,c(2,2))
log(params)
Now assume there is a 0 in some matrix cells. Furthermore, assume you want a 0 to appear in the output for such cells.
How would you compute the solution now?
Notice that log(0) is not a nice number.

Resources