Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have:

z = data.frame(x1=a, x2=b, x3=c, etc)

I am trying to do:

for (i in 1:10)
{
    paste(c('N'),i,sep="") -> paste(c('z$x'),i,sep="")
}

Problems:

  1. paste(c('z$x'),i,sep="") yields "z$x1", "z$x1" instead of calling the actual values. I need the expression to be evaluated. I tried as.numeric, eval. Neither seemed to work.

  2. paste(c('N'),i,sep="") yields "N1", "N2". I need the expression to be merely used as name. If I try to assign it a value such as paste(c('N'),5,sep="") -> 5, ie "N5" -> 5 instead of N5 -> 5, I get target of assignment expands to non-language object.

This task is pretty trivial since I can simply do:

N1 = x1... N2 = x2...

etc, but I want to learn something new

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
119 views
Welcome To Ask or Share your Answers For Others

1 Answer

I'd suggest using something like for( i in 1:10 ) z[,i] <- N[,i]...

BUT, since you said you want to learn something new, you can play around with parse and substitute.

NOTE: these little tools are funny, but experienced users (not me) avoid them.

This is called "computing on the language". It's very interesting, and it helps understanding the way R works. Let me try to give an intro:

The basic language construct is a constant, like a numeric or character vector. It is trivial because it is not different from its "unevaluated" version, but it is one of the building blocks for more complicated expressions.

The (officially) basic language object is the symbol, also known as a name. It's nothing but a pointer to another object, i.e., a token that identifies another object which may or may not exist. For instance, if you run x <- 10, then x is a symbol that refers to the value 10. In other words, evaluating the symbol x yields the numeric vector 10. Evaluating a non-existant symbol yields an error.

A symbol looks like a character string, but it is not. You can turn a string into a symbol with as.symbol("x").

The next language object is the call. This is a recursive object, implemented as a list whose elements are either constants, symbols, or another calls. The first element must not be a constant, because it must evaluate to the real function that will be called. The other elements are the arguments to this function.

If the first argument does not evaluate to an existing function, R will throw either Error: attempt to apply non-function or Error: could not find function "x" (if the first argument is a symbol that is undefined or points to something other than a function).

Example: the code line f(x, y+z, 2) will be parsed as a list of 4 elements, the first being f (as a symbol), the second being x (another symbol), the third another call, and the fourth a numeric constant. The third element y+z, is just a function with two arguments, so it parses as a list of three names: '+', y and z.

Finally, there is also the expression object, that is a list of calls/symbols/constants, that are meant to be evaluated one by one.

You'll find lots of information here:

https://github.com/hadley/devtools/wiki/Computing-on-the-language

OK, now let's get back to your question :-)

What you have tried does not work because the output of paste is a character string, and the assignment function expects as its first argument something that evaluates to a symbol, to be either created or modified. Alternativelly, the first argument can also evaluate to a call associated with a replacement function. These are a little trickier, but they are handled by the assignment function itself, not by the parser.

The error message you see, target of assignment expands to non-language object, is triggered by the assignment function, precisely because your target evaluates to a string.

We can fix that building up a call that has the symbols you want in the right places. The most "brute force" method is to put everything inside a string and use parse:

parse(text=paste('N',i," -> ",'z$x',i,sep=""))

Another way to get there is to use substitute:

substitute(x -> y, list(x=as.symbol(paste("N",i,sep="")), y=substitute(z$w, list(w=paste("x",i,sep="")))))

the inner substitute creates the calls z$x1, z$x2 etc. The outer substitute puts this call as the taget of the assignment, and the symbols N1, N2 etc as the values.

parse results in an expression, and substitute in a call. Both can be passed to eval to get the same result.

Just one final note: I repeat that all this is intended as a didactic example, to help understanding the inner workings of the language, but it is far from good programming practice to use parse and substitute, except when there is really no alternative.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...