簡體   English   中英

R- ode function(deSolve包):改變一個參數的值作為時間的function

[英]R- ode function (deSolve package): change the value of a parameter as a function of time

我正在嘗試使用 deSolve package 中的deSolve ode求解一階微分方程。 問題如下:葯物在某些時候(輸注時間)以恆定的輸注速率給葯,並以一級速率消除。 因此,該過程可以描述為:

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

其中t是時間, Infusion_times是包含給葯時間的向量, C是葯物的量, Ke是其消除常數, Infusion是一個變量,取輸液時的輸液速度值,以及否則值為 0。 因此,假設我們要施用 3 劑,從時間 0、24 和 40 開始,每次輸注持續兩個小時,假設我們希望deSolve每 0.02 個單位時間計算一次答案。 例如,我們希望deSolve求解 0 到 48 之間時間的微分方程,步長為 0.02 倍單位。 因此,我們為ode function 指定時間的向量將是:

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(from = 40, to = 42, by = 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 function 所需的其他值:

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

現在,讓我們根據需要編寫一個 function 說明變化率:

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 , 只是Ke )。 現在,讓我們解方程:

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

讓我們 plot 結果:

library(ggplot2)

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

如果Infusion總是等於 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的值,並且有效! 因此,我對這些行為完全感到困惑。 這不是改變變量值的問題,也不是浮點數之間的比較問題......知道這些可能是什么嗎? 謝謝

大多數deSolve求解器使用自動內部時間步長,該時間步長會根據系統的粗糙度或平滑度自行調整。 The use of if statements or if() functions in the model function is not a good idea for two reasons: (i) the time steps may not be hit exactly and (2) the model function (ie the derivative) should ideally be continuous和可微分並避免逐步行為,即使求解器在這種情況下非常穩健。

deSolve package 為您的問題提供了兩種方法:“強制函數”和“事件”。 兩者都有其優點和缺點,但如果“事件”(例如注入)的時間與積分時間步相比非常短,則“事件”特別有用。

有關這方面的更多信息,請參見 deSolve幫助頁面?forcings forcings 和?eventsdeSolve: Forcing functions and Events from the user,2017 Conference 以及 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行是確保模擬命中所有事件時間的一種可能方法。 它通常由求解器自動完成,並且可能會發出警告以提醒用戶對此要非常小心。

我使用“基礎”plot 和rug來指示注射時間。

我有點想知道Infusion_timesInf_rate這兩個術語。 在基於事件的方法中,在離散時間點將“數量”添加到 state 變量 C 中,而“速率”表示在時間間隔內連續添加。 這通常稱為強制 function。

強制 function 會更簡單並且數值更好。

我一直在為同樣的問題苦苦掙扎一段時間。 我試圖復制 IV 輸液,然后使用 deSolve package 而不是原始 Z20F35E630DAF44DBFA4C3F68F5399D8 中使用的 RxODE package 進行 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)}

在這里, Num.Doses設置為 5 次 IV 輸注。 Tau (給葯間隔)是 24 小時, 0是輸注開始時間, 2是輸注結束時間(以小時為單位)。

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

我從 Andrew Booker 那里得到了Infusion <-行的想法,如https://github.com/andrewooker/PopED/issues/11所示。 我將他的建議從if else修改為ifelse並在第 5 次輸液結束后合並一個硬停止, time <= max(Inf.Times)否則 model 將不斷重新輸液。 這也允許我在使用 deSolve 運行 model 時使用事件表實現額外的非 IV 給葯:

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

當使用完整的 model 運行時,output 與在 RxODE 中使用原始代碼幾乎相同,更直接和“干凈”。 根據 AUC 判斷,差異很小,無花果相同到 6 位數。 我能夠復制 IV 輸液(第一組 5 個峰),還可以概括 PO 給葯(第二組 5 個峰)。 在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM