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

3
  • 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. Commented Mar 30, 2012 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: stackoverflow.com/search?q=[r]+preallocate Commented Mar 31, 2012 at 3:29
  • thanks joran: memory preallocation is the correct way to do this! Commented Apr 12, 2012 at 15:02

5 Answers 5

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
Sign up to request clarification or add additional context in comments.

Comments

9

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

Comments

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.

Comments

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)

1 Comment

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
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.