-5

I have vectors A, B, and C which are of class character. I want them to be numeric, and rather than writing this a bunch of times:

A <- as.numeric(A)

I'd much rather write one expression that converts them all. How can I do that?

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
fpt
  • 358
  • 3
  • 11
  • 3
    If you stored them in a list `l`, then you could use `lapply(l, as.numeric)`. – josliber Jul 09 '14 at 18:16
  • This suggestion is at best incomplete because it returns a list of new vectors which are numeric, leaving the original ones untouched. How then might I assign the list of the vectors to now be the output from lapply(l, as.numeric)? Also if you're going to suggest an answer it'd be better to post it as an answer. Comments are better used to clarify the original question or to ask that such clarification be made. – fpt Jul 09 '14 at 19:08
  • 3
    I think you're misunderstanding the point of the suggestion. If there are collections of objects you want to operate on as a group, then it is typically considered a _mistake_ in R to _not_ place them all in a single structure like a list. The suggestion is aimed at what is arguably your "true" problem, i.e. not storing A, B, C, etc in a list in the first place. – joran Jul 09 '14 at 19:12
  • Why is this question being modded down? – fpt Jul 09 '14 at 19:12
  • 2
    Let me see... 1- Reproducible example? No. 2- Showed us what you've tried? No. 3- Being polite to people who are trying to help you free of charge? No. I can go on if you like – David Arenburg Jul 09 '14 at 19:21
  • 2
    @joran has it exactly right -- if you really have so many objects that it's a hassle to convert them individually with `as.numeric`, then you've stored your data in the wrong way. R doesn't provide a clean way to replace the values of sets of variables -- you'll either need to mess with environments as the currently posted answer does or do ill-advised `assign` and `get` calls, operating on variable names. – josliber Jul 09 '14 at 19:22
  • 3
    @DavidArenburg: not quite sure about point #3, "impolite". Negative, yes. Impolite, maybe not. (Re OP comment 1: I often post short, off-the-cuff ideas for answers as comments, figuring that they can be fleshed out/corrected/posted as answers later if they deserve it. This may be wrong but I find it an effective way to work.) – Ben Bolker Jul 09 '14 at 21:32
  • @BenBolker, Impolite- yes. When a 50 rep user tells a 7K+ user (that is trying to help him) how he should use the comments in a manner like he is his father or something- I would even consider it rude – David Arenburg Jul 10 '14 at 07:29
  • Yeouch! I failed to anticipate how ugly this threa—uh, issue could turn out! I had hoped there was something simple I was missing, like how most Lisp objects can work as generalized variables, in which case, pretending there's an analogous Lisp function as.numeric, I could simply `(mapcar #'(lambda (x) (setf x (as.numeric x))) list-of-variables)`. Eventually it turned out @ben-bolker's suggested use of `get` was the simple thing I was missing. – fpt Jul 10 '14 at 17:15

1 Answers1

3

Well the obvious way is to put them into a list and *apply the conversion:

result = sapply(list(A, B, C), as.numeric, simplify = FALSE)

But unpacking the results again gets messy:

A = result$A
# … etc.

but you can just use result as its own environment-like object if you just need to access the objects temporarily:

local({
    do_something_with(A)
    and_also(B, C)
}, result)

Alternatively, the following code also works but it’s a bit dodgy (list application with side effects always is, and assigning into a parent scope is doubly so):

invisible(list2env(lapply(mget(c('A', 'B', 'C')), as.numeric), environment())

I advise against this.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • +1 for giving the OP rope and advising them not to hang themselves – Ben Bolker Jul 09 '14 at 21:08
  • 2
    If I actually wanted to do this I would use `for (i in c("A","B","C")) assign(i,as.numeric(get(i)))` -- i.e. do everything in the current environment to avoid explicit environment manipulation – Ben Bolker Jul 09 '14 at 21:11
  • 1
    @Ben My reason for not posting this (besides avoiding `for`) is that it doesn’t really save over individual conversion and assignment. Now, of course my solution doesn’t either, but mine is trivially encapsulated in a function. Of course this point is kind of moot since I explicitly advise against doing this anyway. ;-) – Konrad Rudolph Jul 09 '14 at 21:25
  • Did you mean `lapply` rather than `apply`? I get an error if I use `apply`. If I use `lapply` the results aren't named; I need `lapply(list(A=A,B=B,C=C),...)` (ugh; I wish base R had a [function that created a list with automatic names](http://stackoverflow.com/questions/16951080/can-list-objects-be-created-in-r-that-name-themselves-based-on-input-object-name/16951524#16951524)) – Ben Bolker Jul 09 '14 at 21:36
  • @Ben Oh thanks for catching that, I meant `sapply` (to get named arguments, hence `simplify=FALSE`). I am using `*apply` in the text now to make it clear that I’m taking about the generic family of functions, rather than one specific function. – Konrad Rudolph Jul 09 '14 at 21:45
  • 1
    Not sure if this is any better, but there is also `list2env` instead of the `assign` route: `toGet <- c("A", "B", "C"); list2env(lapply(mget(toGet), as.numeric), envir=.GlobalEnv)`. – A5C1D2H2I1M1N2O1R2T1 Jul 10 '14 at 02:17
  • @BenBolker, does `mget` help in any way with your concerns about names? – A5C1D2H2I1M1N2O1R2T1 Jul 10 '14 at 02:17
  • @Ananda Good points, I always forget about the side-effect variant of `list2env`. Terrible function, what did its author think? And I didn’t know about `mget`, this will simplify [some actual code](https://github.com/klmr/modules/blob/7bed38cf88b6299fc11c6cae188bded5ced4ef6e/R/export_submodule.r#L24-L26) I have. – Konrad Rudolph Jul 10 '14 at 09:06