【问题标题】:Multiplying variables identified by vectors in R将R中的向量标识的变量相乘
【发布时间】:2018-03-07 16:21:12
【问题描述】:

我需要为 6*3 变量手动创建交互项。我已将这些变量的名称存储到两个向量中,我们称它们为 a 和 b。让我们将我的数据框称为 df。

a <- c("var1","var2","var3")
b <- c("varA","varB","varC","varD","varE","varF")

我可以手动创建 18 个不同的变量,如下所示:

df$var1.A <- df$var1*df$varA
df$var1.B <- df$var1*df$varB
df$var2.A <- df$var2*df$varA  
df$var2.B <- df$var2*df$varB

等等等等,但这显然是不雅且容易出错的。我尝试过使用 apply、sapply 等,但还没有找到解决方案。

更新

感谢@akrun,他的回答让我走上了正确的道路。但是,我现在需要计算另一组交互,这次使用“转换”,所以基本语法是

df <- transform(df, var1.A = var1*varA)
df <- transform(df, var2.A = var2*varA)
df <- transform(df, var1.B = var1*varB)
df <- transform(df, var2.B = var1*varB)

对于其他 17 个交互,依此类推。我试图调整 @akrun 提供的代码来完成这项任务,但没有成功。

我需要计算这些交互项的原因是我正在使用 Amelia 来乘以估算缺失数据。由于交互将在我的分析中,我需要在估计缺失值时将它们包括在内,而 Amelia 不会自动为我这样做。所以我计算了 18 个交互项,并让 Amelia 生成了一些估算数据集。但是,推算的交互项不一定与其组成项一致,后者也缺少 Amelia 推算的数据。因此,为了运行我的分析,我需要根据完整值和估算值计算新的交互项。 Amelia 的开发人员建议通过“变换”来做到这一点,如果将其应用于整个 Amelia 对象,则适用于所有插补。我无法使用 'df$var1.A

结束更新

有人可以帮忙吗?

同时将正确的值分配给函数中正确的位置并创建一个名称以折叠由“。”分隔的相乘变量的名称的任何解决方案将不胜感激。

非常感谢!

【问题讨论】:

  • 这个? mapply(function(x,y){paste(x,y,sep = "*")},a,b)
  • 您想要的确切结果是什么?

标签: r apply


【解决方案1】:

我们可以通过在vectors 上执行expand.grid 一次性完成这一切

ab <- expand.grid(a, b, stringsAsFactors = FALSE)

根据向量的扩展组合创建新的列名

nm1 <- sub("\\.var", ".", do.call(paste, c(ab, sep=".")))  

然后遍历每一行,对列进行子集化,乘以并分配输出以创建新列

df[nm1] <- apply(ab , 1, FUN = function(x) Reduce(`*`, df[x]))
df
#var1 var2 var3 varA varB varC varD varE varF var1.A var2.A var3.A var1.B var2.B var3.B var1.C var2.C var3.C var1.D var2.D var3.D var1.E var2.E var3.E var1.F
#1    3    9    6    9    1    7    3    2    5     27     81     54      3      9      6     21     63     42      9     27     18      6     18     12     15
#2    3    3    4    2    5    1    3    7    4      6      6      8     15     15     20      3      3      4      9      9     12     21     21     28     12
#3    7    7    7    1    7    6    4    6    3      7      7      7     49     49     49     42     42     42     28     28     28     42     42     42     21
#4    5    8    7    5    2    6    2    7    2     25     40     35     10     16     14     30     48     42     10     16     14     35     56     49     10
#5    6    3    3    2    3    1    9    9    1     12      6      6     18      9      9      6      3      3     54     27     27     54     27     27      6
#  var2.F var3.F
#1     45     30
#2     12     16
#3     21     21
#4     16     14
#5      3      3

数据

set.seed(24)
df <- as.data.frame(matrix(sample(1:9, 5 * 9, replace = TRUE), 
         5, 9, dimnames = list(NULL, c(a, b))))

【讨论】:

  • 工作正常!但是我仍然没有得到 OP 想要的东西。
  • @AndreElrico 谢谢,根据 OP 的描述,想要创建 18 列,在我扩展的“ab”中,它是 18 列 length(nm1) #[1] 18
  • @akrun 谢谢一百万!这正是我所需要的。
  • @akrun 对不起,如果我再次打扰您,但我需要执行一组相关但不同的转换。我需要使用“转换”,因此基于您提供的数据的基本语法将是:'df
  • 我现在已经更新了我原来的问题,所以它反映了这个额外的请求。再次感谢!
【解决方案2】:

如果y 是您的响应变量,则像这样运行您的线性模型:

lm(y ~ (var1 + var2 + var3) * (varA + varB + varC + varD + varE + varF), df)

这将给出第一组和第二组之间的截距、主要效果和交互作用,但不在每组之间(这是我对你想要什么的理解)。

如果想法是使用ab 那么:

fo <- sprintf("y ~ (%s) * (%s)", paste(a, collapse = "+"), paste(b, collapse = "+"))
lm(fo, df)

例如使用内置的anscombe data.frame:

lm(y1 ~ (y2 + y3) * (x1 + x2 + x3 + x4), anscombe)

给予:

Call:
lm(formula = y1 ~ (y2 + y3) * (x1 + x2 + x3 + x4), data = anscombe)

Coefficients:
(Intercept)           y2           y3           x1           x2           x3  
   259.9304       8.6943     -47.1185     -25.9360           NA           NA  
         x4        y2:x1        y2:x2        y2:x3        y2:x4        y3:x1  
    -0.2124       0.1627           NA           NA           NA       3.5765  
      y3:x2        y3:x3        y3:x4  
         NA           NA           NA  

【讨论】:

  • 我不想将其作为答案发布,因为它基于在您的模型背景中创建的数据集,但如果他们真的需要他们可以使用的数据:@987654328 @ 并忽略拦截列。还有一种更通用的方法:data.frame(model.matrix(as.formula(sprintf("~ (%s) * (%s)", paste(a, collapse = "+"), paste(b, collapse = "+"))), df))
  • 感谢 G. Grothendieck!不是我需要的,但我不知道这种语法,将来可能会很有帮助!
【解决方案3】:

简单

setNames(merge(a, b), c("col1", "col2"))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    相关资源
    最近更新 更多