用于在R中用nleqslv求解许多非线性方程的循环

时间:2016-01-03 22:18:10

标签: r loops nonlinear-functions

我在使用R中的import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //Create Label let paybackLabel = UILabel(frame: CGRectMake(0, 0, 300, 41)) paybackLabel.center = CGPointMake(190, 284) paybackLabel.textAlignment = NSTextAlignment.Center paybackLabel.font = UIFont(name: paybackLabel.font.fontName, size: 40) paybackLabel.textColor = UIColor.whiteColor() paybackLabel.text = "Hello World" self.view.addSubview(paybackLabel) //Create Slider let paybackSlider = UISlider(frame: CGRectMake (45,546,310,31)) paybackSlider.minimumValue = 0 paybackSlider.maximumValue = 1000 paybackSlider.continuous = true paybackSlider.tintColor = UIColor.blueColor() paybackSlider.value = 500 paybackSlider.addTarget(self, action: "paybackSliderValueDidChange:",forControlEvents: .ValueChanged) self.view.addSubview(paybackSlider) } func paybackSliderValueDidChange(sender: UISlider!) { print("payback value: \(sender.value)") paybackLabel.text = "\(sender.value)" } } 解决许多非线性方程时遇到问题,以便求解距离默认度量。这是我的第一个R代码,所以我仍然在努力解决一些问题。我的代码看起来像这样(小型化为三个案例的data.frame):

nleqslv

我的问题是,我的代码只给了我一个解决方案,这意味着我的循环首先不能正常工作。循环应该克服这个事实,library("nleqslv") D <- c(28000000, 59150000, 38357000) VE <- c(4257875, 10522163.6, 31230643) R <- c(0.059883, 0.059883, 0.059883) SE <- c(0.313887897, 0.449654737, 0.449734826976691) df <- data.frame(D, VE, R, SE) for(i in 1:nrow(df)){ fnewton <- function(x){ y <- numeric(2) d1 <- (log(x[1]/df$D[i])+(df$R[i]+x[2]^2/2))/x[2] d2 <- d1-x[2] y1 <- df$VE[i]-(x[1]*pnorm(d1)-exp(-df$R[i])*df$D[i]*pnorm(d2)) y2 <- df$SE[i]*df$VE[i]-pnorm(d1)*x[2]*x[1] y } xstart <- c(df$VE[i], df$SE[i]) df$VA[i] <- nleqslv(xstart, fnewton, method="Newton")$x[1] df$SA[i] <- nleqslv(xstart, fnewton, method="Newton")$x[2] i=i+1 } 首先是长度为2的向量,但是我的数据(或我的例子)是一个比2更长的向量。我尝试了一些东西,但是我无法处理这个问题,我认为有一个简单的解决方案,但我没有看到我的错误。

2 个答案:

答案 0 :(得分:0)

代码中有一些简单的错误。

1)正如mra68评论的那样,将fnewton函数中的y1,y2更改为y[1]y[2]

2)删除最后一行i=i+1    (下一个i由行for(i in 1:nrow(df)){自动映射。)

3)(可选)使用VA,SA指定初始化df。

这是最终的工作代码:

library("nleqslv")
D <- c(28000000, 59150000, 38357000)
VE <- c(4257875, 10522163.6, 31230643)
R  <- c(0.059883, 0.059883, 0.059883)
SE <- c(0.313887897, 0.449654737, 0.449734826976691)
df <- data.frame(D, VE, R, SE, VA=numeric(3), SA=numeric(3))

for(i in 1:nrow(df)){

  fnewton <- function(x){
    d1 <- (log(x[1]/df$D[i])+(df$R[i]+x[2]^2/2))/x[2]
    d2 <- d1-x[2]

    y <- numeric(2)
    y[1] <- df$VE[i]-(x[1]*pnorm(d1)-exp(-df$R[i])*df$D[i]*pnorm(d2))
    y[2] <- df$SE[i]*df$VE[i]-pnorm(d1)*x[2]*x[1]
    y
  }

  xstart <- c(df$VE[i], df$SE[i])
  df$VA[i] <- nleqslv(xstart, fnewton, method="Newton")$x[1]
  df$SA[i] <- nleqslv(xstart, fnewton, method="Newton")$x[2]
}

答案 1 :(得分:0)

skwon的代码可以通过在for循环外定义fnewton函数并将变量dfi放在参数中来提高效率。像这样

fnewton <- function(x,df,i){
  d1 <- (log(x[1]/df$D[i])+(df$R[i]+x[2]^2/2))/x[2]
  d2 <- d1-x[2]

  y <- numeric(2)
  y[1] <- df$VE[i]-(x[1]*pnorm(d1)-exp(-df$R[i])*df$D[i]*pnorm(d2))
  y[2] <- df$SE[i]*df$VE[i]-pnorm(d1)*x[2]*x[1]
  y
}

然后将循环更改为此

for(i in 1:nrow(df)){
    xstart <- c(df$VE[i], df$SE[i])
    z <- nleqslv(xstart, fnewton,  method="Newton",control=list(trace=1), df=df,i=i)
    df$VA[i] <- z$x[1]
    df$SA[i] <- z$x[2]
}

如果函数fnewton变得更复杂,你也可以使用包compiler来加速它(一点点)。

最后你应该测试nleqslv实际上是否通过测试z$termcd==1找到了解决方案。如果没有,则跳过分配z$x值。我会留给你的。