使用lm()时以1/var作为第二个变量出现错误结果的原因排查
为什么lm()公式右侧直接用1/变量会导致回归无斜率?
我有一个包含两个变量的数据框,需要对变量的倒数进行绘图并执行线性回归。
初始尝试的代码
linear_mod <- lm((1/df$var1[3:length(var1)]) ~ # 跳过前两个0值,避免出现1/0的错误 (1/df$var2[3:length(var2)])) png("lineweaver-burk_glc6p.png", height = 400) plot(1/(df$var1), 1/(df$var2)) abline(linear_mod)
遇到的问题
运行上述代码后,得到的回归结果只有截距y=0.897,完全没有斜率项。
可行的解决方法
提前将变量的倒数赋值给临时变量,再执行回归就能得到正确的结果(回归直线为0.83022 + 0.01768x):
temp1 <- 1/df$var1[3:length(df$var1)] temp2 <- 1/df$var2[3:length(df$var2)] linear_mod <- lm(temp1 ~ temp2)
测试过程中的发现
- 只有当临时变量作为
~右侧的变量时,回归才会输出斜率; - lm()似乎可以接受
~左侧的1/df$var1[3:length(var1)]写法,但不接受~右侧的相同写法; - 去掉
~右侧变量的1/后就能得到斜率,用2+df$var...作为右侧变量也能正常运行,只有/符号出现在~右侧时会触发问题; - 用
c()包裹~右侧的变量可以正常工作,但不清楚为什么~左侧的变量不需要这样做。
数据框示例
| var2 | var1 |
|---|---|
| 0 | 0.0133976420150054 |
| 0 | 0.00803858520900322 |
| 0.1 | 1.17363344051447 |
| 0.1 | 1.13076098606645 |
| 0.2 | 2.05787781350482 |
| 0.2 | 2.18113612004287 |
| 0.2 | 1.7524115755627 |
| 0.2 | 0.844051446945338 |
| 0.2 | 1.42550911039657 |
| 0.3 | 0.244908896034298 |
| 0.3 | 0.616291532690247 |
| 0.3 | 1.39067524115756 |
| 0.3 | 0.669882100750268 |
| 0.3 | 1.66934619506967 |
| 0.3 | 1.56752411575563 |
| 0.3 | 1.33976420150054 |
| 0.4 | 1.83547695605573 |
| 0.4 | 1.77920685959271 |
| 0.5 | 1.83547695605573 |
| 0.5 | 1.84887459807074 |
| 1 | 1.92390139335477 |
| 2 | 1.94533762057878 |
| 2 | 1.7470525187567 |
原因解释
问题出在R的公式语法规则上:/是公式中的特殊运算符,用于表示嵌套模型(比如a/b会被解析为a + a:b,即主效应加交互项),而非数学意义上的除法。当你在~右侧写1/df$var2[...]时,R会把它当作嵌套模型处理,而非计算倒数,最终导致回归只生成截距项。
而~左侧的表达式会被直接当作响应变量计算,不会触发公式的特殊运算符解析——因为公式左侧只允许单个响应变量(或向量表达式),R会直接执行数学运算得到响应向量,所以1/df$var1[...]可以正常工作。
其他可行写法
除了用临时变量,还可以用以下两种方式解决:
- 用
I()函数包裹除法表达式,明确告诉R这是数学运算而非公式语法:
linear_mod <- lm(I(1/df$var1[3:length(df$var1)]) ~ I(1/df$var2[3:length(df$var2)]))
- 先预处理数据框,生成倒数列后再用列名构建公式(推荐,代码更清晰):
library(dplyr) df_processed <- df %>% slice(3:n()) %>% # 跳过前两行 mutate(rev_var1 = 1/var1, rev_var2 = 1/var2) linear_mod <- lm(rev_var1 ~ rev_var2, data = df_processed)
内容的提问来源于stack exchange,提问作者DragonStaty
相关产品推荐
相关产品推荐

