-1

I am new using R and while working on a research for college I wrote this code:

pixel <- function(a){z <- 22-a%/%22 ; y <- a-22*a%/%22 
                b <- c(y, z)
                return(b)}
a <- c(339, 339, 270, 383, 205, 269, 275, 413, 203, 364, 365, 317, 318, 342, 360, 408, 319, 278, 339, 317, 294)
archivos <- list.files(pattern = "sR.")

for (j in 1:length(archivos)) {
        assign("n", nc_open(archivos[j]))
        assign("r", ncvar_get(eval(n), "pcp"))
        assign(sprintf("o%d", j), c(1:length(a))) 
        for (i in 1:length(a){
                y <- pixel(a[i])[1] 
                z <- pixel(a[i])[2]
                eval(as.name(sprintf("o%d", j)))[i] <- r[y,x]
                } 
}

I intend to store the output of the pixel function into a vector created for each value of the j loop.

I believe the last part of the code is the problem and I tested the following code:

> eval(as.name(sprintf("o%d", 1)))[1]
[1] 89

I can retrieve the first value of the vector o1, which is 89, but when trying to put a new value in that position R doesn't allow me to:

> eval(as.name(sprintf("o%d", 1)))[1]<-1
Error in eval(as.name(sprintf("o%d", 1)))[1] <- 1 : 
  target of assignment expands to non-language object

The final output are empty vectors (o1, o2, etc.). I've been looking for different approaches to do this but I am stuck.

I would be glad to hear suggestions.

noriega
  • 447
  • 1
  • 9
  • 23

2 Answers2

1

As for your function, it's already vectorized, so let's just return a matrix with a y and a z column instead of sticking them together in a vector. Then we can run it on a all at once instead of using a for loop:

pixel <- function(a) {
    z <- 22 - a %/% 22
    y <- a - 22 * a %/% 22
    b <- matrix(c(y, z), ncol = 2)
    colnames(b) = c("y", "z")
    return(b)
}

pixel(a)
 #       y  z
 # [1,]  9  7
 # [2,]  9  7
 # [3,]  6 10
 # [4,]  9  5
 # [5,]  7 13
 # [6,]  5 10
 # [7,] 11 10
 # [8,] 17  4
 # [9,]  5 13
 # ...

For your other stuff, it's hard to make specific changes without a reproducible example, but in general if you are using assign you are overcomplicating things. Better to use a list. There is a lot of discussion about this over in How to make a list of data frames?.

Something like this ought to get you started

archivos <- list.files(pattern = "sR.")
r_list = lapply(archivos, nc_open)
p_list = lapply(r_list, ncvar_get, "pcp")

I'm not sure what the last line of your code is trying to do, but you've got all the ingredients in a much easier to work with form now.

Community
  • 1
  • 1
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • I really appreciate the help. It is impressive what the apply functions can do and, as I said earlier, I'm new programming in R and the use of apply functions is kind of hard to understand yet. But when all the rush from college is over I would try to recode my initial approach. For now on I will try to include your suggestions into future code. Thank you a lot! – noriega Oct 31 '16 at 22:27
1

after several attempts I came up with a solution, not elegant nor impressive but functional (even though the code, as Gregor mentioned above, is kind of overcomplicated) :

for (j in 1:length(archivos)) {
        assign("n", nc_open(archivos[j]))
        assign("r", ncvar_get(eval(n), "pcp"))
        **assign(sprintf("o%d", j), c(1:length(a)))** I omitted this
        for (i in 1:length(a){
                y <- pixel(a[i])[1] 
                z <- pixel(a[i])[2]
                **prec[i] <- r[y,z]
                assign(sprintf("o%d", j), prec)** I added this
                } 
}

In brief, I created a temporal list called prec[i] wich is recorded using the assign function with the name o1, o2, etc.

As I said it is not elegant but it works for now until I improve all the code. Thank you all.

noriega
  • 447
  • 1
  • 9
  • 23