Home > Software design >  assign and get for dataframe variables in r
assign and get for dataframe variables in r

Time:11-09

If I want to have variables with numbers accessible for example in a for loop I can use get and assign:

for(i in 1:2){
    assign(paste0('a',toString(i)),i*pi)
}
get('a2')

output

[1] 6.283185

But what if I want to do something similar for a dataframe?

I would like to do something like

df<-data.frame(matrix(ncol = 2,nrow = 3))
varnames <- c()
for(i in 1:2){
    varnames <- c(varnames, paste0('a', toString(i)))
}
colnames(df) <- varnames
for(i in 1:2){
    assign(paste0('df$a',toString(i)), rep(i*pi,3))
}
get(paste0('df$a',toString(2)))

But this actually just creates variables called df$a1, df$a2 instead of assigning c(i*pi,i*pi,i*pi) to the columns of the dataframe df

And what I really want to do is to be able manipulate whole columns (individual entries) like this:

for(i in 1:2){
    for(j in 1:3)
        assign(paste0('df$a',toString(i),'[',toString(j),']'), i*pi)
}
get(paste0('df$a',toString(2),'[2]'))

where I would be able to get df$a2[2].

I think something like a python dictionary would work too.

CodePudding user response:

Instead of assign, just directly do the [

for(i in 1:2) df[[paste0('a', i)]] <- rep(i * pi, 3)

and then can get the value with

df[[paste0('a', 2)]][2]
[1] 6.283185

assign can be used, but it is not recommended when we have do this more directly

for(i in 1:2) assign("df",`[[<-`(df, paste0('a', i), value = i * pi))
 df[[paste0('a', 2)]][1]
[1] 6.283185

The get should be on the object i.e. 'df' instead of the columns i.e.

get('df')[[paste0('a', 2)]][1]

CodePudding user response:

First of all, it is not generally a great idea to use assign to create objects in the global environment. In preference, you should be creating a named list instead for all sorts of good reasons, not least of which is the ability to iterate over the objects you create.

Secondly, note that the block of code:

varnames <- c()
for(i in 1:2){
    varnames <- c(varnames, paste0('a', toString(i)))
}
colnames(df) <- varnames

Can be replaced with the one-liner:

colnames(df) <- paste0("a", 1:2)

Finally, you should take advantage of R's vectorization and the ability to subset with ["colname"] notation. This removes the need for an explicit loop altogether here:

df[paste0("a", 1:2)] <- sapply(1:2, \(i) rep(i * pi, 3))

df
#>         a1       a2
#> 1 3.141593 6.283185
#> 2 3.141593 6.283185
#> 3 3.141593 6.283185
  • Related