簡體   English   中英

如何從公式/字符串中刪除兩個連續的加號 (+)?

[英]how can I remove two consecutive pluses (+) from a formula/string?

例如,我有一個這樣的公式:

main_var ~ 0 + var1:x + var2:y + var3 + + var4 + (0 + main_var|x_y) + (0 + add_var|x_y) + (1|x_y)

如何刪除var3var4之間的兩個連續加號 (+)(只留下一個)?

可以在不強制轉換為字符串的情況下編輯公式的組成部分。 公式包含兩部分,一個表達式(您編寫的部分)和一個環境(您編寫它的地方,其中可能包含表達式中引用的變量)。 我們想要堅持的環境; 我們想要改變的表達方式。

表達式(這里我指的是符號和調用之類的語言對象,而不是狹義的expression類)是語法樹,其行為有點像列表。 它們可以是子集:

f <- main_var ~ 0 + var1:x + var2:y + var3 + + var4 + (0 + main_var|x_y) + (0 + add_var|x_y) + (1|x_y)

f[[1]]
#> `~`
f[[2]]
#> main_var
f[[3]]
#> 0 + var1:x + var2:y + var3 + +var4 + (0 + main_var | x_y) + (0 + 
#>     add_var | x_y) + (1 | x_y)
f[[3]][[3]]
#> (1 | x_y)

並因此迭代。 因為它們是樹狀結構,要遍歷整棵樹,我們需要遞歸。 大多數函數對於遞歸非常典型(返回原子葉節點;遞歸帶有子節點的節點),但棘手的部分是識別我們想要更改的部分的條件。 如果您查看有問題的節點,它包含一個一元(帶一個參數) +調用:

f <- main_var ~ 0 + var1:x + var2:y + var3 + + var4 + (0 + main_var|x_y) + (0 + add_var|x_y) + (1|x_y)
f[[3]][[2]][[2]][[2]][[3]]
#> +var4
f[[3]][[2]][[2]][[2]][[3]][[1]]
#> `+`
f[[3]][[2]][[2]][[2]][[3]][[2]]
#> var4

所有其他+調用都是二進制的。 因此,我們可以檢查第一個節點是+長度為 2 的節點。 事實證明,獲得+表達式也有點棘手; 最簡單的是experssion(+)[[1]]quote(+1)[[1]] ,但是一旦有了它,相等性檢查就會照常工作。

將碎片拼湊起來,並通過將碎片強制恢復為表達式和公式來進行清理,

remove_unary_plus <- function(expr){
    if (length(expr) == 1) {
        # return atomic elements
        return(expr) 
    } else if (length(expr) == 2 && expr[[1]] == expression(`+`)[[1]]) {
        # for unary plus calls, return the argument without the plus
        return(expr[[2]]) 
    } else {
        # otherwise recurse, simplifying the results back to a language object
        clean_expr <- as.call(lapply(expr, remove_unary_plus))

        # if it's a formula, hold on to the environment
        if (inherits(expr, "formula")) {
            clean_expr <- as.formula(clean_expr, env = environment(expr))
        }

        return(clean_expr)
    }
}

f_clean <- remove_unary_plus(f)
f_clean
#> main_var ~ 0 + var1:x + var2:y + var3 + var4 + (0 + main_var | 
#>     x_y) + (0 + add_var | x_y) + (1 | x_y)

看,它保持它的環境:

str(f)
#> Class 'formula'  language main_var ~ 0 + var1:x + var2:y + var3 + +var4 + (0 + main_var | x_y) +      (0 + add_var | x_y) + (1 | x_y)
#>   ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
str(f_clean)
#> Class 'formula'  language main_var ~ 0 + var1:x + var2:y + var3 + var4 + (0 + main_var | x_y) + (0 +      add_var | x_y) + (1 | x_y)
#>   ..- attr(*, ".Environment")=<environment: R_GlobalEnv>

顯然,這對於日常的公式操作來說有點痛苦,但是,這是可能的,可能對編程使用有用,並且(至少對我來說)很有趣。

就像是

as.formula( gsub( ""\\+s*\\+", "+", deparse(f)))

其中f是您的公式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM