将向量转换为公式

时间:2018-12-18 12:23:52

标签: r

给出一个data.frame和一个仅具有-1,0,1且长度等于data.frame列数的向量。是否存在一种自然的方法将向量转换为公式,而元素的位置-1出现在公式的左侧,而元素+1出现在公式的右侧?

例如,给定以下data.frame

df = data.frame(
  'a' = rnorm(10),
  'b' = rnorm(10),
  'c' = rnorm(10),
  'd' = rnorm(10),
  'e' = rnorm(10))

及其后的向量vec = c(-1,-1,0,1,1)

是否存在一种自然的方式来构建公式a+b~d+e

2 个答案:

答案 0 :(得分:1)

我们假设如果vec中没有1,那么我们应该使用1的右手边,如果vec中没有-1,那么左侧为空。

每个替代项都会生成一个字符串,但是如果需要公式类对象,请使用formula(s),其中s是该字符串。

1)粘贴每侧子集化对应于vec -1的名称以给出LHS并粘贴/折叠它们,对vec 1进行相同的名称以给出RHS并将其粘贴〜一起。如果我们知道vec中至少有一个1,则可以省略if语句。在这里的解决方案中,这似乎是最简单的。

nms <- names(df)
LHS <- paste(nms[vec == -1], collapse = "+")
RHS <- paste(nms[vec == 1], collapse = "+")
if (RHS == "") RHS <- "1"
paste0(LHS, "~", RHS)
## [1] "a+b~d+e"

2)适当地:将LHS和RHS线交替合并为一个sapply。如果我们知道vec中至少有一个1,那么我们可以 通过省略if语句来简化代码。这种方法比(1)短。

sa <- sapply(c(-1, 1), function(x) paste(names(df)[vec == x], collapse = "+"))
if (sa[2] == "") sa[2] <- "1"
paste0(sa[1], "~", sa[2])
## [1] "a+b~d+e"

3)轻按,我们可以像这样将LHS和RHS线交替组合成单个tapply

ta <- tapply(names(df), vec, paste, collapse = "+")
paste0(if (any(vec == -1)) ta[["-1"]], "~", if (any(vec == 1)) ta[["1"]] else 1)
## [1] "a+b~d+e"

如果我们知道-1和1在vec中至少出现一次,那么我们可以将最后一行简化为:

paste0(ta[["-1"]], "~", ta[["1"]]])
## [1] "a+b~d+e"

总的来说,如果可以保证至少有一个1和至少一个-1,那么这种方法是最短的,但是与其他方法相比,处理边缘情况似乎有些麻烦。

答案 1 :(得分:0)

我们可以通过paste

创建一个组来做到这一点
paste(aggregate(nm ~ vec, subset(data.frame(nm = names(df), vec, 
    stringsAsFactors = FALSE), vec != 0),
    FUN = paste, collapse= ' + ')[['nm']], collapse=' ~ ')
#[1] "a + b ~ d + e"

或者另一个选择是tapply

paste(tapply(names(df), vec, FUN = paste, 
        collapse= ' + ')[c('-1', '1')], collapse= ' ~ ')
#[1] "a + b ~ d + e"