6

Is there a way to assign a value to a specific column within a data frame? e.g.,

dat2 = data.frame(c1 = 101:149, VAR1 = 151:200)    
j = "dat2[,"VAR1"]"  ## or, j = "dat2[,2]"
assign(j,1:50)

The approach above doesn't work. Neither does this:

j = "dat2"
assign(get(j)[,"VAR1"],1:50)
smci
  • 32,567
  • 20
  • 113
  • 146
baha-kev
  • 3,029
  • 9
  • 33
  • 31
  • You'll need to expand a little more on why you would do this. you can use `foo='VAR1'; dat2[,foo]<-1:50` instead and still pass your strings around if you're so moved. – Justin Mar 27 '13 at 21:57
  • Why? -- to create a bunch of arbitrarily named data frames, and populate a specific column in them. I understand it is preferable to use a list structure for this; however, it would be useful to have another option. – baha-kev Mar 27 '13 at 22:12

2 Answers2

16

lets assume that we have a valid data.frame with 50 rows in each

dat2 <- data.frame(c1 = 1:50, VAR1 = 51:100)

1 . Don't use assign and get if you can avoid it.

"dat2[,"VAR1"]" is not valid in R.

You can also note this from the help page for assign

assign does not dispatch assignment methods, so it cannot be used to set elements of vectors, names, attributes, etc.

Note that assignment to an attached list or data frame changes the attached copy and not the original object: see attach and with.

A column of a data.frame is an element of a list

What you are looking for is [[<-

# assign the values from column (named element of the list) `VAR1`
j <- dat2[['VAR1']] 

If you want to assign new values to VAR1 within dat2,

dat2[['VAR1']] <- 1:50

The answer to your question....

To manipulate entirely using character strings using get and assign

assign('dat2', `[[<-`(get('dat2'), 'VAR1', value = 2:51))

Other approaches

data.table::set

if you want to assign by reference within a data.frame or data.table (replacing an existing column only) then set from the data.table package works (even with data.frames)

library(data.table)
set(dat2, j = 'VAR1', value = 5:54)

eval and bquote

dat1 <- data.frame(x=1:5)
dat2 <- data.frame(x=2:6)



for(x in sapply(c('dat1','dat2'),as.name)) {
  eval(bquote(.(x)[['VAR1']] <- 2:6))
}

eapply

Or if you use a separate environment

ee <- new.env()
ee$dat1 <- dat1
ee$dat2 <- dat2

# eapply returns a list, so use list2env to assign back to ee
list2env(eapply(ee, `[[<-`, 'y', value =1:5), envir = ee)

mnel
  • 113,303
  • 27
  • 265
  • 254
  • Don't forget `dat[, "VAR1"]`. – krlmlr Mar 27 '13 at 22:11
  • 1
    @krlmlr -- I prefer `[[<-` for single assignments. – mnel Mar 27 '13 at 22:17
  • Keep in mind that the thrust of my question has to do with get/assign -- in other words, I want to name and refer to the data frame by a character value. I think `set()` will work in this way, just have to replace `set(dat2, ...)` with `set(get(), ...)`. Thanks. – baha-kev Mar 27 '13 at 22:29
  • @baha-kev -- set will not create a column, only replacing values in existing columns – mnel Mar 27 '13 at 22:32
  • Huh? `set` is not a function in base or recommended R packages. – IRTFM Mar 27 '13 at 22:33
  • @DWin -- the text mentions `data.table`, forgot the explicit call to `library(data.table)`.... Its there now. – mnel Mar 27 '13 at 22:35
  • Your last "really ugly" approach is what I was looking for. If you could move it to the top of your answer, that would be great. Thanks! – baha-kev Mar 27 '13 at 23:19
6
set2 <- function(x,  val) {
   eval.parent(substitute(x <- val))
 }

> dat2 = data.frame(c1 = 101:150, VAR1 = 151:200)
> set2(dat2[["VAR1"]], 1:50)
> str(dat2)
'data.frame':   50 obs. of  2 variables:
 $ c1  : int  101 102 103 104 105 106 107 108 109 110 ...
 $ VAR1: int  1 2 3 4 5 6 7 8 9 10 ...
IRTFM
  • 258,963
  • 21
  • 364
  • 487