R-ode函数(deSolve包):将参数值更改为时间的函数

R-ode函数(deSolve包):将参数值更改为时间的函数,r,ode,equation-solving,R,Ode,Equation Solving,我试图用deSolve软件包中的函数ode来解一阶微分方程。问题如下:药物在某些时间以恒定的输注速率输注,并以一阶速率消除。因此,该过程可以通过以下方式描述: if(t %in% Infusion_times){Infusion <- Infusion_rate} else{Infusion <- 0} dC <- -Ke*C + Infusion 输液时间如下所示: Infusion_times <- c(seq(from = 0, to = 2, by =

我试图用deSolve软件包中的函数ode来解一阶微分方程。问题如下:药物在某些时间以恒定的输注速率输注,并以一阶速率消除。因此,该过程可以通过以下方式描述:

if(t %in% Infusion_times){Infusion <- Infusion_rate} else{Infusion <- 0}
    dC <- -Ke*C + Infusion
输液时间如下所示:

Infusion_times <- c(seq(from = 0, to = 2, by = 0.02), seq(from = 24, to = 26, by = 0.02), 
                    seq(from = 40, to = 42, by = 0.02))
如您所见,100%输液时间中的所有值都包含在向量时间中,因此变量输液应该在指定时间取输液率值。然而,当我们解方程时,它不起作用。 让我们证明一下,但首先,让我们指定ode函数所需的其他值:

parameters <- c(Ke = 0.5)
amounts <- c(C = 0) #Initial value for drug is 0
Inf_rate <- 5
让我们绘制结果图:

library(ggplot2)

ggplot(as.data.frame(out)) + geom_line(aes(x = times, y = C))
这与输液量始终等于0时得到的结果完全相同。 但是,请注意,如果我们只模拟单一剂量,并尝试类似的方法,它将起作用:

OneComp <- function(t, amounts, parameters){
      with(as.list(c(amounts, parameters)),{
          if(t < 2){Infuse =Inf_rate} else{Infuse = 0}
          dC <- -Ke*C + Infuse
      list(c(dC))})
    }
out <- ode(func = OneComp, y = amounts, parms = parameters, times = times)
ggplot(as.data.frame(out)) + geom_line(aes(x = times, y = C))
在这里,我们让变量Infuse仅在时间小于2小时时才取Inf_rate的值,并且有效! 因此,我对这些行为完全感到困惑。这不是改变变量值的问题,也不是比较浮点数的问题。。。你知道这些是什么吗?多亏了

大多数解算器使用自动内部时间步长,根据系统的粗糙度或平滑度自行调整。在模型函数中使用if语句或IFF函数不是一个好主意,原因有两个:i时间步长可能不会精确命中;2模型函数(即导数)理想情况下应该是并避免分步行为,即使在这种情况下解算器非常稳健

deSolve包提供了两种解决问题的方法:强制函数和事件。两者都有各自的优点和缺点,但如果事件的时间(例如注入)与积分时间步长相比非常短,则事件尤其有用

有关这方面的更多信息,请参见deSolve帮助页面?强制力和?事件,在中,从用户处!2017年大会,以及来自userR!2014年

请检查以下各项是否适用于您:

library("deSolve")

OneComp <- function(t, y, parms){
  with(as.list(c(y, parms)),{
    dC <- -Ke * C
    list(c(dC))
  })
}

eventfunc <- function(t, y, parms) {
  with(as.list(c(y, parms)),{
    C + Inf_rate
  })
}

parms <- c(Ke = 0.5, Inf_rate = 5)

y0 <- c(C = 0)            # Initial value for drug is 0

Infusion_times <- c(seq(from =  0, to =  2, by = 0.02), 
                    seq(from = 24, to = 26, by = 0.02), 
                    seq(from = 40, to = 42, by = 0.02))

# time step can be made bigger to speedup simulation
times <- round(seq(from = 0, to = 48, by = .1) , 2)

# check that all events are in 'times', but no duplicates
# this check is also done by the solver and may print a warning
# to ensure that the user is very careful with this
unique_times <- cleanEventTimes(times, Infusion_times)
times        <- sort(c(unique_times, Infusion_times))

out <- ode(func = OneComp, y = y0, parms = parms, times = times, 
           events = list(func = eventfunc, time = Infusion_times))

plot(out)
rug(Infusion_times)
两条cleanEventTimes线是确保所有事件时间都被模拟命中的一种可能方法。它通常由解算器自动完成,并可能发出警告,提醒用户对此非常小心

我用底图和地毯来表示注射时间

我对输液次数和注射率这两个术语有些疑惑。在基于事件的方法中,在离散时间点向状态变量C添加一个量,而速率表示在一个时间间隔内连续添加。这通常称为强制函数

强制函数更简单,数值效果更好。

大多数解算器使用自动内部时间步长,根据系统的粗糙度或平滑度自行调整。在模型函数中使用if语句或IFF函数不是一个好主意,原因有两个:i时间步长可能不会精确命中;2模型函数(即导数)理想情况下应该是并避免分步行为,即使在这种情况下解算器非常稳健

deSolve包提供了两种解决问题的方法:强制函数和事件。两者都有各自的优点和缺点,但如果事件的时间(例如注入)与积分时间步长相比非常短,则事件尤其有用

有关这方面的更多信息,请参见deSolve帮助页面?强制力和?事件,在中,从用户处!2017年大会,以及来自userR!2014年

请检查以下各项是否适用于您:

library("deSolve")

OneComp <- function(t, y, parms){
  with(as.list(c(y, parms)),{
    dC <- -Ke * C
    list(c(dC))
  })
}

eventfunc <- function(t, y, parms) {
  with(as.list(c(y, parms)),{
    C + Inf_rate
  })
}

parms <- c(Ke = 0.5, Inf_rate = 5)

y0 <- c(C = 0)            # Initial value for drug is 0

Infusion_times <- c(seq(from =  0, to =  2, by = 0.02), 
                    seq(from = 24, to = 26, by = 0.02), 
                    seq(from = 40, to = 42, by = 0.02))

# time step can be made bigger to speedup simulation
times <- round(seq(from = 0, to = 48, by = .1) , 2)

# check that all events are in 'times', but no duplicates
# this check is also done by the solver and may print a warning
# to ensure that the user is very careful with this
unique_times <- cleanEventTimes(times, Infusion_times)
times        <- sort(c(unique_times, Infusion_times))

out <- ode(func = OneComp, y = y0, parms = parms, times = times, 
           events = list(func = eventfunc, time = Infusion_times))

plot(out)
rug(Infusion_times)
两条cleanEventTimes线是确保所有事件时间都被模拟命中的一种可能方法。它通常由解算器自动完成,并可能发出警告,提醒用户对此非常小心

我用底图和地毯来表示注射时间

我对输液次数和注射率这两个术语有些疑惑。在基于事件的方法中,在离散时间点向状态变量C添加一个量,而速率表示在一个时间间隔内连续添加。这通常称为强制函数


强制函数会更简单,而且在数值上更好。

我已经为同样的问题挣扎了一段时间。我尝试使用deSolve包而不是原始模型中使用的RxODE包来复制静脉输注,然后进行PO给药。我的解决方案是列出输液时间,然后提取最大值:

tmp <- c()
for (i in seq(from = 1, to = Num.Doses, by = 1)) {
tmp[i] <- (i * Tau) - Tau
tmp2 <- seq(from = 0, to = 2, by = 0.1)
Inf.Times <- round(unlist(lapply(tmp, function(x, Add) x + tmp2)), 3)}

我有了输液的想法我已经为同样的问题挣扎了一段时间。我尝试使用deSolve包而不是原始模型中使用的RxODE包来复制静脉输注,然后进行PO给药。我的解决办法是 s列出输液时间,然后提取最大值:

tmp <- c()
for (i in seq(from = 1, to = Num.Doses, by = 1)) {
tmp[i] <- (i * Tau) - Tau
tmp2 <- seq(from = 0, to = 2, by = 0.1)
Inf.Times <- round(unlist(lapply(tmp, function(x, Add) x + tmp2)), 3)}

我得到了输液的想法是的,这是我在一段时间后得到的答案,我从伯克利麦当娜那里用了一种与你相似的方法改编了它。deSolve是一个非常通用的解决方案包,我不确定它是否是PK或PKPD问题的最佳选择。如前所述,请避免ODE模型中的if、ifelse等,无论它是deSolve还是其他什么,尤其是带有自动时间步解算器的。它可能会起作用,但它肯定会损害数值计算,并会不必要地减慢模拟速度。@tpetzoldt,我同意避免if和ifelse加速执行。在这种情况下,deSolve和RxODE之间的性能在人均时间上分别为0.15秒和0.01秒。然而,100名受试者使用相同的给药方案进行PopPK模拟,分别需要15秒和0.5秒。RxODE编译模型并避免if、ifelse,但数值结果是等效的。根据您关于使用强制函数的建议,我没有足够的知识来编写必要的代码。一些基准测试表明,性能可以与纯C或Fortran实现相媲美。但是,如果RxODE符合您的要求,那么没有什么可以反对它的使用。我真的很感激能在不同的软件包之间做出选择。事实上,R在众多的软件包中提供了很大的灵活性。我当然感谢您在deSolve上的所有努力@tpetzoldt,因为这是我最喜欢的ODEs。我终于能够根据您发布的教程链接为这个问题编写代码并执行强制函数。就像任何事情一样,对大量的尝试和错误有一点耐心是很有帮助的。是的,这是我在一段时间后得到的答案,我从伯克利麦当娜那里用了一种与你相似的方法改编了它。deSolve是一个非常通用的解决方案包,我不确定它是否是PK或PKPD问题的最佳选择。如前所述,请避免ODE模型中的if、ifelse等,无论它是deSolve还是其他什么,尤其是带有自动时间步解算器的。它可能会起作用,但它肯定会损害数值计算,并会不必要地减慢模拟速度。@tpetzoldt,我同意避免if和ifelse加速执行。在这种情况下,deSolve和RxODE之间的性能在人均时间上分别为0.15秒和0.01秒。然而,100名受试者使用相同的给药方案进行PopPK模拟,分别需要15秒和0.5秒。RxODE编译模型并避免if、ifelse,但数值结果是等效的。根据您关于使用强制函数的建议,我没有足够的知识来编写必要的代码。一些基准测试表明,性能可以与纯C或Fortran实现相媲美。但是,如果RxODE符合您的要求,那么没有什么可以反对它的使用。我真的很感激能在不同的软件包之间做出选择。事实上,R在众多的软件包中提供了很大的灵活性。我当然感谢您在deSolve上的所有努力@tpetzoldt,因为这是我最喜欢的ODEs。我终于能够根据您发布的教程链接为这个问题编写代码并执行强制函数。和任何事情一样,一点点耐心,加上大量的尝试和错误,会有很大的帮助。
OneComp <- function(t, amounts, parameters){
      with(as.list(c(amounts, parameters)),{
          if(t < 2){Infuse =Inf_rate} else{Infuse = 0}
          dC <- -Ke*C + Infuse
      list(c(dC))})
    }
out <- ode(func = OneComp, y = amounts, parms = parameters, times = times)
ggplot(as.data.frame(out)) + geom_line(aes(x = times, y = C))
library("deSolve")

OneComp <- function(t, y, parms){
  with(as.list(c(y, parms)),{
    dC <- -Ke * C
    list(c(dC))
  })
}

eventfunc <- function(t, y, parms) {
  with(as.list(c(y, parms)),{
    C + Inf_rate
  })
}

parms <- c(Ke = 0.5, Inf_rate = 5)

y0 <- c(C = 0)            # Initial value for drug is 0

Infusion_times <- c(seq(from =  0, to =  2, by = 0.02), 
                    seq(from = 24, to = 26, by = 0.02), 
                    seq(from = 40, to = 42, by = 0.02))

# time step can be made bigger to speedup simulation
times <- round(seq(from = 0, to = 48, by = .1) , 2)

# check that all events are in 'times', but no duplicates
# this check is also done by the solver and may print a warning
# to ensure that the user is very careful with this
unique_times <- cleanEventTimes(times, Infusion_times)
times        <- sort(c(unique_times, Infusion_times))

out <- ode(func = OneComp, y = y0, parms = parms, times = times, 
           events = list(func = eventfunc, time = Infusion_times))

plot(out)
rug(Infusion_times)
tmp <- c()
for (i in seq(from = 1, to = Num.Doses, by = 1)) {
tmp[i] <- (i * Tau) - Tau
tmp2 <- seq(from = 0, to = 2, by = 0.1)
Inf.Times <- round(unlist(lapply(tmp, function(x, Add) x + tmp2)), 3)}
Model <- function(time, yini, parameters) {
  with(as.list(c(yini, parameters)), {
    Infusion <- ifelse(time %% Tau < Inf.Time & time <= max(Inf.Times), Dose / Inf.Time, 0)
    C1 <- Central / V1
    dDepot <- - (Ka * Depot)
    dCentral <- (Ka * Depot) - (CL * C1) + Infusion
    list(c(dDepot, dCentral))})}
Dose.Events <- data.frame(var = "Depot", time = c(120, 144, 168, 192, 216), value = Dose2, method = "add")
Times <- seq(from = 0, to = Tot.Hours, by = 1)
out <- ode(y = Ini.Con, times = Times, func = Model2, parms = Parms, events = list(data = Dose.Events))