MW Frost
MW Frost

Reputation: 990

Specifying column names from a list in the data.frame command

I have a list called cols with column names in it:

cols <- c('Column1','Column2','Column3')

I'd like to reproduce this command, but with a call to the list:

data.frame(Column1=rnorm(10))

Here's what happens when I try it:

> data.frame(cols[1]=rnorm(10))

Error: unexpected '=' in "data.frame(I(cols[1])="

The same thing happens if I wrap cols[1] in I() or eval().

How can I feed that item from the vector into the data.frame() command?

Update:

For some background, I have defined a function calc.means() that takes a data frame and a list of variables and performs a large and complicated ddply operation, summarizing at the level specified by the variables.

What I'm trying to do with the data.frame() command is walk back up the aggregation levels to the very top, re-running calc.means() at each step and using rbind() to glue the results onto one another. I need to add dummy columns with 'All' values in order to get the rbind to work properly.

I'm rolling cast-like margin functionality into ddply, basically, and I'd like to not retype the column names for each run. Here's the full code:

cols <- c('Col1','Col2','Col3')
rbind ( calc.means(dat,cols),
    data.frame(cols[1]='All', calc.means(dat, cols[2:3])),
    data.frame(cols[1]='All', cols[2]='All', calc.means(dat, cols[3]))
)

Upvotes: 4

Views: 11069

Answers (4)

Adam Erickson
Adam Erickson

Reputation: 6363

I believe the assign() function is your answer:

cols <- c('Col1','Col2','Col3')
data.frame(assign(cols[1], rnorm(10)))

Returns:

   assign.cols.1...rnorm.10..
1                 -0.02056822
2                 -0.03675639
3                  1.06249599
4                  0.41763399
5                  0.38873118
6                  1.01779018
7                  1.01379963
8                  1.86119518
9                  0.35760039
10                 1.14742560

With the lapply() or sapply() function, you should be able to loop the cbind() process. Something like:

operation <- sapply(cols, function(x) data.frame(assign(x, rnorm(10))))
final     <- data.frame(lapply(operation, cbind))

Returns:

   Col1.assign.x..rnorm.10.. Col2.assign.x..rnorm.10.. Col3.assign.x..rnorm.10..
1                0.001962187                -0.3561499               -0.22783816
2               -0.706804781                -0.4452781               -1.09950505
3               -0.604417525                -0.8425018               -0.73287079
4               -1.287038060                 0.2545236               -1.18795684
5                0.232084366                -1.0831463                0.40799046
6               -0.148594144                 0.4963714               -1.34938144
7                0.442054119                 0.2856748                0.05933736
8                0.984615916                -0.0795147               -1.91165189
9                1.222310749                -0.1743313                0.18256877
10              -0.231885977                -0.2273724               -0.43247570

Then, to clean up the column names:

colnames(final) <- cols

Returns:

          Col1       Col2        Col3
1   0.19473248  0.2864232  0.93115072
2  -1.08473526 -1.5653469  0.09967827
3  -1.90968422 -0.9678024 -1.02167873
4  -1.11962371  0.4549290  0.76692067
5  -2.13776949  3.0360777 -1.48515698
6   0.64240694  1.3441656  0.47676056
7  -0.53590163  1.2696336 -1.19845723
8   0.09158526 -1.0966833  0.91856639
9  -0.05018762  1.0472368  0.15475583
10  0.27152070 -0.2148181 -1.00551111

Cheers,

Adam

Upvotes: 0

Marek
Marek

Reputation: 50704

There is one trick. You could mess with lists:

cols_dummy <- setNames(rep(list("All"), 3), cols)

Then if you use call to list with one paren then you should get what you want

data.frame(cols_dummy[1], calc.means(dat, cols[2:3]))

You could use it on-the-fly as setNames(list("All"), cols[1]) but I think it's less elegant.

Example:

some_names <- list(name_A="Dummy 1", name_B="Dummy 2") # equivalent of cols_dummy from above
data.frame(var1=rnorm(3), some_names[1])
#        var1  name_A
# 1 -1.940169 Dummy 1
# 2 -0.787107 Dummy 1
# 3 -0.235160 Dummy 1

Upvotes: 1

Eduardo Leoni
Eduardo Leoni

Reputation: 9050

Use can use structure:

cols <- c("a","b")

foo <- structure(list(c(1, 2 ), c(3, 3)), .Names = cols, row.names = c(NA, -2L), class = "data.frame")

I don't get why you are doing this though!

Upvotes: 3

frankc
frankc

Reputation: 11473

I'm not sure how to do it directly, but you could simply skip the step of assigning names in the data.frame() command. Assuming you store the result of data.frame() in a variable named foo, you can simply do:

names(foo) <- cols

after the data frame is created

Upvotes: 1

Related Questions