Henrik
Henrik

Reputation: 14450

How can I use assign to change variables within a dataframe in R?

I tried to do something like this:

x <- data.frame(1:20)  
attach(x)  
assign("x2",1:20,pos="x")  

However, x$x2 gives me NULL.
With x2 I get what I want but it is not part of the data.frame.

Attaching x2 to x manually would work in this simple case but not in the more complex one I need. I try to assign in a loop where I loop over the varnames used in the assign call.

Upvotes: 1

Views: 4845

Answers (3)

Gavin Simpson
Gavin Simpson

Reputation: 174813

There are lots of ways to assign a variable etc, and which is best will depend on personal taste. However, a couple of points:

You don't want to be attach()ing anything. It will work fine 9 times out of 10 and then bite you in the ass when you don't expect it, because all you are doing is placing a copy of your object on the search path. Modify the original object and the one on the search path doesn't change to match.

I personally don't like accessing things with $ in general use. It is ugly and engenders a tendency for users to just delve into objects and rip things out as they wish. Doesn't matter so much for your data, but when I see people doing model$residuals I get worried. There are better ways (in this case resid()). Some users also riddle their model formulas with $.

If you are writing scripts for a data analysis that you might come back to months or years later, anything that can help you understand what your code is doing is an invalable bonus in my opinion. I find with() and within() useful for the sort of problem you had because they are explicit about what you want to do.

This is clearer:

x <- data.frame(X = rnorm(10))
with(x, mean(X))
x <- within(x, Y <- rpois(10, 3))

than

x <- data.frame(X = rnorm(10))
mean(x$X)
x$Y <- rpois(10, 3)
## or
x["Y"] <- rpois(10, 3)

Even though they do the same thing.

assign() inside a within() call is just a waste of typing, is it not?

Upvotes: 4

Charles
Charles

Reputation: 4469

Try using within:

x <- data.frame(x=1:20)
x <- within(x, {
  x2 <- x^2
  assign('x3', x2 * 2)
  # ... other assignments
})

It is cleaner to use $ and [[ though, which also gets the column ordering right:

x <- data.frame(x=1:20)
x$x2 <- x$x^2
x[['x3']] <- x$x2 * 2

Upvotes: 5

Joshua Ulrich
Joshua Ulrich

Reputation: 176648

The Details section of ?assign tells you why your code behaves the way it does.

Why not something simple like:

x["x2"] <- 1:20

Upvotes: 4

Related Questions