R- ode 函数(deSolve 包):将参数值更改为时间的函数 [英] R- ode function (deSolve package): change the value of a parameter as a function of time

查看:246
本文介绍了R- ode 函数(deSolve 包):将参数值更改为时间的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 deSolve 包中的函数 ode 来求解一阶微分方程.问题如下:药物在某些时间(输注时间)以恒定输注速率给药,并以一级速率消除.因此,该过程可以描述为:

if(t %in% Infusion_times){Infusion <- Infusion_rate} else{Infusion <- 0}dC <- -Ke*C + 输注

其中 t 是时间,Infusion_times 是包含给药时间的向量,C 是药物的数量,Ke是它的消除常数,Infusion是一个变量,有输液时取输液速度的值,否则取0.因此,假设我们要进行 3 次给药,从 0、24 和 40 次开始,每次输注持续两个小时,并且我们希望 deSolve 每 0.02 个时间单位计算一次答案.例如,我们希望 deSolve 以 0.02 次单位的步长求解 0 到 48 次之间的微分方程.因此,我们指定 ode 函数的时间的向量将是:

times <- seq(from = 0, to = 48, by = 0.02)

输液时间由下式给出:

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

起初,我担心问题可能出在浮点数的比较上.为了防止它,我将两个向量四舍五入到小数点后两位:

times <- round(times, 2)Infusion_times <- round(times, 2)

现在,希望所有 Infusion_times 都包含在 times 向量中:

(sum(Infusion_times %in% times)/length(Infusion_times))*100[1] 100

如您所见,Infusion_times 中的所有值(100%)都包含在向量times 中,因此变量Infusion应该在指定的时间取值 Infusion_rate.然而,当我们解方程时,它不起作用.让我们证明一下,但首先,让我们指定 ode 函数所需的其他值:

参数 <- c(Ke = 0.5)数量 <- c(C = 0) #药物的初始值为 0Inf_rate <- 5

现在,让我们根据需要编写一个函数来说明变化率:

OneComp <- function(t, amount, parameters){with(as.list(c(amounts, parameters)),{if(t %in% Infusion_times){Infuse =Inf_rate} else{Infuse = 0}dC <- -Ke*C + 注入列表(c(dC))})}

对于那些不熟悉 deSolve 包的人,函数的参数 t 将说明方程应该被积分的次数,amounts 将指定 C 的初始值,parameters 将给出参数的值(在这种情况下,只是 Ke).现在,让我们解方程:

out <- ode(func = OneComp, y = amount, parms = parameters, times = times)

让我们绘制结果:

库(ggplot2)ggplot(as.data.frame(out)) + geom_line(aes(x = times, y = C))

如果 Infusion 总是等于 0,我们会得到完全相同的结果.但是,请注意,如果我们只模拟单一剂量,并且我们要尝试类似的方法,它会起作用:

OneComp <- function(t, amount, parameters){with(as.list(c(amounts, parameters)),{if(t < 2){Infuse =Inf_rate} else{Infuse = 0}dC <- -Ke*C + 注入列表(c(dC))})}out <- ode(func = OneComp, y = 数量,parms = 参数,时间 = 次数)ggplot(as.data.frame(out)) + geom_line(aes(x = times, y = C))

这里,我们让变量Infuse只在时间小于2小时时取Inf_rate的值,它起作用了!因此,我对这些行为感到非常困惑.这不是改变变量值的问题,也不是浮点数之间比较的问题......知道这些是什么吗?谢谢

解决方案

我一直在为同样的问题苦苦挣扎一段时间.我试图使用 deSolve 包而不是原始模型中使用的 RxODE 包复制 IV 输注,然后进行 PO 给药.我的解决方案是列出输液时间,然后提取最大值:

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

此处,Num.Doses 设置为 5 次 IV 输注.Tau(给药间隔)为 24 小时,0 是输液开始时间,2 是输液结束时间,单位为小时.

接下来我构建了一个模型,其完整版本是来自 RxODE 的多室 PKPD 模型(

I am trying to solve a first-order differential equation using the function ode from the deSolve package. The problem is as follows: a drug is administered by a constant infusion rate at some times (infusion times) and eliminated in a first-order rate. Thus, the process can be described by:

if(t %in% Infusion_times){Infusion <- Infusion_rate} else{Infusion <- 0}
    dC <- -Ke*C + Infusion

where t is the time, Infusion_times is a vector containing at what times the drug is administered, C is the quantity of the drug, Ke is its elimination constant and Infusion is a variable taking the value of the infusion rate when there is infusion, and the value 0 otherwise. So, let's say we want to administer 3 doses, starting at times 0, 24 and 40, with each infusion lasting for two hours, and let's say we want deSolve to compute the answer every 0.02 units of time. We want deSolve to solve the differential equation for the times between 0 and 48 with steps of 0.02 times unit, for instance. So our vector specifying the times to the ode function would be:

times <- seq(from = 0, to = 48, by = 0.02)

The infusion times are given by:

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))

At first, I was concerned that the problem could be in the comparison of floating-points. To prevent it, I rounded both vectors to two decimal places:

times <- round(times, 2)
Infusion_times <- round(times, 2)

So now, hopefully, all Infusion_times are included in the times vector:

(sum(Infusion_times %in% times)/length(Infusion_times))*100
[1] 100

As you can see, all the values in Infusion_times (100%) are contained in the vector times, and thus the variable Infusion should take the value Infusion_rate at the specified times. However, when we solve the equation, it doesn't work. Let's prove it, but first, let's specify the other values needed by the ode function:

parameters <- c(Ke = 0.5)
amounts <- c(C = 0) #Initial value for drug is 0
Inf_rate <- 5

And now, let's write a function stating the rate of changes, just as required:

OneComp <- function(t, amounts, parameters){
  with(as.list(c(amounts, parameters)),{
      if(t %in% Infusion_times){Infuse =Inf_rate} else{Infuse = 0}
      dC <- -Ke*C + Infuse
  list(c(dC))})
}

For those who are not familiar with the deSolve package, the argument t of the function will state the times for which the equation should be integrated, amounts will specify the initial value of C and parameters will give the value of the parameters (in this case, just Ke). And now, let's solve the equation:

out <- ode(func = OneComp, y = amounts, parms = parameters, times = times)

Let's plot the results:

library(ggplot2)

ggplot(as.data.frame(out)) + geom_line(aes(x = times, y = C))

This is exactly the same result we would get if Infusion was always equal to 0. However, note that if we were to mimic only a single dose, and we were to try a similar approach, it would work:

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))

Here, we have made the variable Infuse take the value of the Inf_rate only when the time is less than 2 hours, and it works! Therefore, I am totally puzzled with these behaviour. It is not a problem of changing the value of a variable, it is not a problem of a comparison between floating-point numbers... Any idea of what could these be? Thanks

解决方案

I have been struggling with the same problem for some time. I was trying to replicate IV infusion followed by PO dosing using the deSolve package rather than the RxODE package used in the original model. My solution was to make a list of infusion times and later extract a maximal value:

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)}

Here, Num.Doses is set for 5 IV infusions. The Tau (dosing interval) is 24 hours, 0 is infusion start time, and 2 is infusion end time in hours.

Next I constructed a model, the full version of which is a multicompartment PKPD model from RxODE (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4728294/):

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))})}

I got the idea for the Infusion <- line from Andrew Booker as shown at https://github.com/andrewhooker/PopED/issues/11. I modified his suggestion from if else to ifelse and incorporated a hard stop after the end of the 5th infusion with the time <= max(Inf.Times) otherwise the model would continually re-infuse. That also allowed me to implement additional non-IV dosing using an events table when running the model using deSolve:

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))

When run using the full model, the output is nearly the same as using the original code in RxODE, which is more straightforward and "clean". The differences, as judged by AUC, were minimal with sig figs the same out to 6 digits. I am able to replicate the IV infusions (first set of 5 peaks) and also recapitulate the PO dosing (second set of 5 peaks).

这篇关于R- ode 函数(deSolve 包):将参数值更改为时间的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆