我正在尝试动态形成一个公式以在
dynlm
中使用。我遇到了一个我不明白的function
行为,从这段代码可以看出:
library(data.table)
dt_test <- data.table("a"=rnorm(10), "b"=1:5)
dt_test[, .(.(
formula("z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2")
)), .(b)]
上面的代码预计会为
b
的每个值生成(相同的)公式。该公式包含在 .(.(...))
中以返回一个列表,以便它可以正确存储在原始 data.table 的列中。
但是,返回的公式与最初提供的字符串不匹配,而是在
+
和 tt
之间添加了一个逗号,从输出中可以看到:
b V1
<int> <list>
1: 1 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + , tt + tt2
2: 2 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + , tt + tt2
3: 3 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + , tt + tt2
4: 4 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + , tt + tt2
5: 5 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + , tt + tt2
本质上,它在没有逗号的地方添加了一个逗号。它甚至会重新排列总和的项,但如果我删除
q_val
,它就会停止这样做。 as.formula
也是如此。
我想了解正在发生的事情并避免它。
这确实很棘手,希望更了解我的底层机制的人可以解释一下。但问题是公式参数的长度:
如果你跑步:
formula(paste0("z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2"))
#> formula(paste0("z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, #2:0) + 1 + tt + tt2"))
#z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 +
# tt + tt2
#>
R 将默认将其打印为 2 行,并在“tt + tt2”处将其截断,因此出于某种原因,data.table 将其视为两个项目。如果你运行
deparse
就可以看到,它会输出一个大小为 2 的字符向量:
[1] "z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + "
[2] " tt + tt2"
要至少从表面上解决此问题,请在
width.cutoff
中使用 deparse
(此处默认为 500):
dt_test[, .(list(
deparse(formula(paste0("z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2")),
width.cutoff = 500)
)), .(b)]
输出:
b V1
<int> <list>
1: 1 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2
2: 2 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2
3: 3 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2
4: 4 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2
5: 5 z_val ~ s_val + q_val + L(s_dval, 32:0) + L(q_dval, 2:0) + 1 + tt + tt2