用户定义的函数变量在某处被覆盖

user defined function variables are getting overwritten somewhere

你好,我有一个用户定义的函数 lambda ,我将年龄(整数)、性别(整数)和一个文件(BMI)传递给它。当我调用它时,我得到了一些值,这是错的。但是当我执行函数中的每个语句时,我得到了正确的答案。奇怪的是

  1. 在我从函数中执行单个语句并获得预期的答案后,如果我再次调用该函数,我会得到正确的答案。
  2. 然后如果在调用函数时更改值,它会给出旧答案(步骤#1)。它永远不会改变,直到我从函数中执行单个语句(如在步骤 #1 中)

谁能帮帮我..

lambda <-function(ag, gnd, ibmi) {

        sel <- subset(ibmi, age==ag & gender == gnd)
        out <- boxcox(lm(sel$bmi~1))
        rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
        return (rn[1] + rn[2])/2
    }

这就是我调用函数的方式..

> lambda(14,1,bmi)
[1] -0.4040404

从 fn

执行每个语句
> sel <- subset(bmi, age==14 & gender == 1)
> out <- boxcox(lm(sel$bmi~1))
> rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
> (rn[1] + rn[2])/2
[1] -0.3636364

我再次调用函数

> lambda(14,1,bmi)
[1] -0.3636364

调用具有不同年龄值的函数

> lambda(17,1,bmi)
[1] -0.3636364

> dput(head(bmi[,c(2,3,4,5,6,7,8,9)], 50))
structure(list(age = c(6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6), gender = c(2L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L), diabetic = structure(c(3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("", "No", "Yes"
), class = "factor"), height = c(117, 117.5, 123, 133.5, 110.2, 
126, 119, 113.8, 125.8, 115.6, 124.1, 117.8, 128, 117, 121, 116.6, 
111.3, 116, 118, 123, 119.5, 118.3, 121.5, 116.4, 121, 110, 114, 
116, 113.5, 115.5, 111.7, 116.5, 121.6, 129.9, 115.3, 116, 116.5, 
122.2, 123.4, 118, 117, 107.2, 116.5, 126.6, 118.2, 119.6, 141, 
118.7, 150.6, 113), weight = c(21.2, 21, 19.2, 36.7, 18.1, 42.6, 
36.2, 18.6, 25.1, 20.1, 40.2, 29.7, 32.6, 20.4, 24.5, 20.9, 17.3, 
22, 21.4, 23.5, 27.5, 23.3, 33.4, 22.2, 24, 16.9, 18.8, 23, 20.1, 
20.8, 26.4, 21.5, 41.2, 47.1, 31.4, 18.9, 27.1, 33.6, 26.2, 21.3, 
20, 17.6, 22.7, 24.3, 19.9, 32, 45.4, 21.4, 20.9, 21.2), bmi = c(15.49, 
15.21, 12.69, 20.59, 14.9, 26.83, 25.56, 14.36, 15.86, 15.04, 
26.1, 21.4, 19.9, 14.9, 16.73, 15.37, 13.97, 16.35, 15.37, 15.53, 
19.26, 16.65, 22.63, 16.39, 16.39, 13.97, 14.47, 17.09, 15.6, 
15.59, 21.16, 15.84, 27.86, 27.91, 23.62, 14.05, 19.97, 22.5, 
17.21, 15.3, 14.61, 15.32, 16.73, 15.16, 14.24, 22.37, 22.84, 
15.19, 9.22, 16.6), systolic = c(108L, 104L, 93L, 103L, 99L, 
103L, 130L, 105L, 131L, 102L, 104L, 137L, 129L, 84L, 116L, 101L, 
108L, 101L, 92L, 111L, 100L, 112L, 107L, 118L, 112L, 104L, 108L, 
140L, 100L, 78L, 103L, 100L, 119L, 106L, 110L, 116L, 100L, 102L, 
96L, 90L, 122L, 104L, 110L, 96L, 106L, 106L, 146L, 120L, 102L, 
116L), diastolic = c(68L, 69L, 65L, 76L, 85L, 73L, 90L, 80L, 
70L, 80L, 78L, 113L, 109L, 64L, 97L, 76L, 63L, 55L, 64L, 86L, 
80L, 94L, 68L, 90L, 77L, 75L, 68L, 120L, 70L, 57L, 70L, 75L, 
78L, 90L, 70L, 67L, 75L, 70L, 68L, 82L, 80L, 71L, 70L, 62L, 71L, 
78L, 87L, 80L, 79L, 89L)), .Names = c("age", "gender", "diabetic", 
"height", "weight", "bmi", "systolic", "diastolic"), row.names = c(NA, 
50L), class = "data.frame")
> 

考虑到所有评论,并结合您的示例,这是一个有效的函数:

library(MASS)
lambda <-function(ag, gnd, ibmi) {
  sel <- ibmi[ibmi$age==ag & ibmi$gender == gnd,]
  out <- boxcox(lm(bmi~1, sel))
  rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
  return(mean(rn))
}

例如:

lambda(6,2,bmi)

有几个(潜在的)问题:

  1. subset 不应在函数内部使用。使用 [ 进行子集化。

  2. 如果将拟合的 lm 模型传递给函数,范围问题很常见。避免这种情况并使用 boxcox 公式方法。

  3. 您的 return 语句中缺少括号。 return 是 R 中的函数。

因此:

lambda <-function(ag, gnd, ibmi) {
  require(MASS)
  sel <- ibmi[ibmi$age==ag & ibmi$gender == gnd,]
  out <- boxcox(bmi~1, data = sel)
  rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
  return((rn[1] + rn[2])/2)
}

lambda(6,2,bmi)
#[1] -0.4040404

sel <- subset(bmi, age==6 & gender == 2)
out <- boxcox(lm(sel$bmi~1))
rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
(rn[1] + rn[2])/2
#[1] -0.4040404

我认为问题出在将 lm class 对象传递给 boxplot 时。只要完全避免使用 lm 就可以了。

lambda <-function(ag, gnd, ibmi) {
  sel <- ibmi[ibmi$age==ag & ibmi$gender == gnd, ]
  out <- boxcox(bmi~1, data = sel)
  rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
  return ((rn[1] + rn[2])/2)
}

> lambda(6,2,bmi)
[1] -0.4040404

正如所见,lm 实际上是多余的。虽然我们仍然可以先使用lm,但是我们必须在lmboxplot函数中都定义data才能正常工作

lambda <-function(ag, gnd, ibmi) {
  sel <- ibmi[ibmi$age==ag & ibmi$gender == gnd, ]
  out <- boxcox(lm(bmi~1, data = sel), data = sel)
  rn <- range(out$x[out$y > max(out$y)-qchisq(0.95,1)/2])
  return ((rn[1] + rn[2])/2)
}