R生成所有可能的交互变量

时间:2015-08-09 14:21:24

标签: r statistics

我有一个带变量的数据框,比如a,b,c,d

dat <- data.frame(a=runif(1e5), b=runif(1e5), c=runif(1e5), d=runif(1e5))

并希望在每个列之间生成所有可能的双向交互项,即:ab,ac,ad,bc,bd,cd。实际上我的数据框有超过100列,所以我无法手动编码。最有效的方法是什么(注意我不想要 b和b a)?

3 个答案:

答案 0 :(得分:12)

您打算如何处理所有这些互动条款?有几种选择,最好取决于你想要做什么。

如果您想将互动传递给lmaov等建模函数,那么它非常简单,只需使用.^2语法:

fit <- lm( y ~ .^2, data=mydf )

以上内容将调用lm并告诉它适合mydf中除y之外的变量的所有主要效果和所有双向互动。

如果由于某种原因您真的想要计算所有互动,那么您可以使用model.matrix

tmp <- model.matrix( ~.^2, data=iris)

这将包括拦截列和主效果列,但如果您不想要它们,可以删除它们。

如果您需要与建模不同的内容,则可以在评论中使用combn函数作为@akrun提及。

答案 1 :(得分:3)

假设预期的输出是列名的组合(来自评论,它应该是a_ba_c等),我们可以在列的名称上使用combn数据集并将m指定为2。

combn(colnames(dat), 2, FUN=paste, collapse='_')
#[1] "a_b" "a_c" "a_d" "b_c" "b_d" "c_d"

如果我们需要在&#39; dat&#39;中乘以列的组合,我们使用列名combn的{​​{1}}输出的每个元素对数据集进行子集化dat[,x[1]],{{1 }),乘以(dat[,x[2]])它,转换为&#39; data.frame&#39; (*),通过data.frame(列名称组合设置列名称(setNames)。我们使用pastelistcbind列表元素中创建输出。

do.call(cbind

基准

do.call(cbind, combn(colnames(dat), 2, FUN= function(x) 
                list(setNames(data.frame(dat[,x[1]]*dat[,x[2]]), 
                 paste(x, collapse="_")) )))
#         a_b        a_c        a_d        b_c        b_d        c_d
#1 0.26929788 0.17697473 0.26453066 0.55676619 0.83221898 0.54691008
#2 0.06291005 0.08337501 0.04455453 0.10370775 0.05542008 0.07344851
#3 0.53789990 0.47301970 0.03112880 0.51305076 0.03376319 0.02969076
#4 0.41596384 0.34920860 0.25992717 0.53948322 0.40155468 0.33711187
#5 0.16878584 0.21232357 0.09196025 0.08162171 0.03535148 0.04447027

注意:基准测试因列数,行数而异。在这里,我使用的是OP的帖子中显示的列数。

数据

set.seed(494)
dat <- data.frame(a=runif(1e6), b=runif(1e6), c=runif(1e6), d=runif(1e6))

greg <- function()model.matrix( ~.^2, data=dat)
akrun <- function() {do.call(cbind, combn(colnames(dat), 2, FUN= function(x) 
           list(setNames(data.frame(dat[,x[1]]*dat[,x[2]]), 
            paste(x, collapse="_")) )))}

system.time(greg())
#  user  system elapsed 
#  1.159   0.024   1.182 

system.time(akrun())
#  user  system elapsed 
#  0.013   0.000   0.013 

library(microbenchmark)
microbenchmark(greg(), akrun(), times=20L, unit='relative')
# Unit: relative
#   expr      min       lq     mean   median       uq      max neval cld
# greg() 39.63122 38.53662 10.23198 18.81274 6.568741 4.642702    20   b
# akrun()  1.00000  1.00000  1.00000  1.00000 1.000000 1.000000    20  a 

答案 2 :(得分:1)

由于model.matrix抱怨的因素只有一个级别,因此您可能想使用stats::terms

labels(terms(~.^2, data = iris[, 1:3]))
# [1] "Sepal.Length"              "Sepal.Width"               "Petal.Length"             
# [4] "Sepal.Length:Sepal.Width"  "Sepal.Length:Petal.Length" "Sepal.Width:Petal.Length"