29

I'm trying a loop like this, where I want to assign the name of the matrix column dynamically:

for(i in 1:nclass){
  P <- eXb / SeXb[mydata$chid]
  mydata <- cbind(mydata, paste("l_", i, sep="")=P)
}

Any idea (apart from changing colnames ex-post)?

Thanks

danfreak
  • 405
  • 1
  • 8
  • 16
  • 2
    I agree with Roman, setting the colnames all at once is better. If it seems frustrating that what you're trying is hard, keep in mind that R doesn't "want" to be used this way, namely the tacking on of columns one at a time like this. It's a subtle hint to rethink your general strategy. – joran Mar 30 '12 at 23:00
  • I'd wager for most R problems, naming of the columns is done post facto. To hammer home joran's point, take a look at the speed improvements available when you preallocate your objects before hand and fill them in vis-a-vis growing them with each iteration: http://stackoverflow.com/search?q=[r]+preallocate – Chase Mar 31 '12 at 03:29
  • thanks joran: memory preallocation is the correct way to do this! – danfreak Apr 12 '12 at 15:02

5 Answers5

17

What about this? You would set column names after you've got your fully worked out matrix finished.

> a <- matrix(1:9, 3)
> a
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> colnames(a) <- paste("col", 1:3, sep = "")
> a
     col1 col2 col3
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
8

If you have the problem that you don't know the number of the added column, you can add and name them by:

df <- data.frame(matrix(1:9, 3, 3))
df
#>  X1 X2 X3
#>1  1  4  7
#>2  2  5  8
#>3  3  6  9

for(i in 1:5){
  df[, ncol(df) + 1] <- rnorm(nrow(df))
  names(df)[ncol(df)] <- paste0("mean_", i)
}

df
#>  X1 X2 X3     mean_1     mean_2    mean_3     mean_4     mean_5
#>1  1  4  7 -1.9983501 -1.6810377 1.2893602  0.5342042 -0.8354363
#>2  2  5  8  0.5966507 -0.5628999 1.2953387 -0.6661931 -0.4685747
#>3  3  6  9 -0.4268952 -2.0069306 0.6390317 -0.3505088  0.1230753
loki
  • 9,816
  • 7
  • 56
  • 82
5

If you aren't set on using cbind, you can also do this:

for(i in 1:nclass){
  P <- eXb / SeXb[mydata$chid]
  mydata[,paste0("l_",i)] <- P
}

Paste0 is just paste with sep = "" which is really handy. Fortunately, paste and paste0 can be used to create new columns without cbind as shown above.

s-heins
  • 679
  • 1
  • 8
  • 20
1
#here I am extracting the generes of movies and assigning to a dataframe
for(i in 1:length(imdb_generes)){ # imdb_generes c("action","friction","scifi")
   genr <- imdb_generes[i]
   a <- somefunction(-----,genr) # somefunction returns c(1,1,0),c(0,1,0),(1,0,0) subsequently
   names(a) <- genr
   my_df <- cbind(my_df,a)
}

my_df
action friction scifi
  1      0        1
  1      1        0
  0      0        0
chit
  • 11
  • 1
1

If I understand your question correctly...

a <- as.data.frame(matrix(1:9, ncol=3))
n <- ncol(a)
b <- as.data.frame(matrix(10:18, ncol=3))
colnames(b) <- c("col2", "col1", "col3")
attach(b)

for (i in 1:ncol(b)) {
  n <- n+1
  d <- get(paste("col", i, sep=""))
  a <- cbind(a, d)
  colnames(a)[n] <- paste("col", i, sep="")
}

print(a)
attitude_stool
  • 1,023
  • 1
  • 13
  • 18
  • Thanks attitude_stool, this is the way, even if as I understood the best way in R in order to increase performance is to first create an empty column (memory preallocation) of the desired size, and then to assign the values – danfreak Apr 12 '12 at 14:59