Set column names while calling a function

2020-07-27 05:10发布

问题:

Consider we have a numeric data.frame foo and want to find the sum of each two columns:

foo <- data.frame(x=1:5,y=4:8,z=10:14, w=8:4)
bar <- combn(colnames(foo), 2, function(x) foo[,x[1]] + foo[,x[2]])
bar
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    5   11    9   14   12   18
#[2,]    7   13    9   16   12   18
#[3,]    9   15    9   18   12   18
#[4,]   11   17    9   20   12   18
#[5,]   13   19    9   22   12   18

Everything is fine, except the column names that are missing from bar. I want column names of bar to show the related columns in foo, for instance in this example:

colnames(bar) <- apply(combn(colnames(foo),2), 2, paste0,collapse="")
colnames(bar)
#[1] "xy" "xz" "xw" "yz" "yw" "zw"

This is simple, but I want to perform column labeling in the same bar <- combn(...) command. Is there anyway?

回答1:

It is possible, but it obfuscates your code. The tradeoff between brevity and clarity here is acute.

To understand how it works, I reference this question.

colnames(x) <- y

Is internally rewritten as

x <- `colnames<-`(x,y)

You can then do the translation yourself.

bar <- `colnames<-`(combn(colnames(foo), 2, function(x) foo[,x[1]] + foo[,x[2]]),
                    apply(combn(colnames(foo),2), 2, paste0,collapse=""))

In many cases, however, it's not worth the mental and syntactic gymnastics required to collapse lines of code in this way. Multiple lines tend to be clearer to follow.



回答2:

You start with a data.frame, not a matrix. Not that important, but it helps to keep up with the jargon we usually use.

What you're after is not possible. If you look at the code of combn, when the result is simplified, it uses no dimension names.

    }
    if (simplify) 
        array(out, dim.use)
    else out
}

You can either hack the function and make it add dimension names, or, you can add it manually to your result post festum.