Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CRAN-SUBMISSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Version: 0.4.0
Date: 2026-01-07 00:45:35 UTC
SHA: 986f44179c3fb67d474c9a965f5643004c47e70c
Version: 0.4.1
Date: 2026-01-10 23:19:31 UTC
SHA: ed329f5dac07bdbb36b0093216bc30c4d0a57514
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: dynamicpv
Title: Evaluates Present Values and Health Economic Models with Dynamic Pricing and Uptake
Version: 0.4.1
Version: 0.4.1.9000
Authors@R: c(
person("Dominic", "Muston", , "dominic.muston@msd.com", role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-4876-7940")),
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# dynamicpv (development version)

* So far, only minor changes to the readme page

# dynamicpv 0.4.1

* Revised vignettes
Expand Down
66 changes: 64 additions & 2 deletions R/dynamic.R
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,34 @@
dynpv <- function(
uptakes = 1,
payoffs,
horizon = length(payoffs),
horizon = NA,
tzero = 0,
prices = rep(1, length(payoffs)+tzero),
prices = NA,
discrate = 0
){
# If payoffs are discrete
if (class(payoffs)=="numeric") {
# Horizon defaults to length of payoffs
if (class(horizon)=="logical") {horizon <- length(payoffs)}
# Price index defaults to (1, ..., 1)
if (class(prices)=="logical") {prices <- rep(1, length(payoffs)+tzero)}
# Call calculation
dpv <- dynpv_discrete(uptakes, payoffs, horizon, tzero, prices, discrate)
}
# If payoffs are not discrete and uptake is discrete
if ((class(uptakes)=="numeric") & (class(payoffs)=="function")) {
dpv <- dynpv_semicts(uptakes, payoffs, horizon, tzero, prices, discrate)
}
# If payoffs and uptake are not discrete
if ((class(uptakes)=="function") & (class(payoffs)=="function")) {
dpv <- dynpv_fullycts(uptakes, payoffs, horizon, tzero, prices, discrate)
}
# Return
return(dpv)
}

# Discrete function
dynpv_discrete <- function(uptakes, payoffs, horizon, tzero, prices, discrate){
# Avoid no visible binding note
j <- k <- l <- uj <- pk <- R <- v <- NULL
# Trim
Expand Down Expand Up @@ -137,3 +160,42 @@ trim_vec <- function(vec){
# Return trimmed vector
return(vec[1:trimto])
}

# Function if payoffs, prices and discounting are functions; but uptakes is a vector
dynpv_semicts <- function(uptakes, payoffs, horizon, tzero, prices, discrate){
# Avoid no visible binding note
j <- uj <- pRv <- pv <- NULL
# Trim
uptakes <- trim_vec(uptakes)
# Integrand function
integrand <- function(k, j) {
payoffs(k) * prices(j+k+tzero) * discrate(j+k)
}
# Create a dataset for each combination of time
df <- expand_grid(j=1:length(uptakes)) |>
dplyr::mutate(
uj = uptakes[j],
pRv = stats::integrate(integrand, lower=0, upper=horizon-j, j=j)$value,
pv = uj * pRv
)
class(df) <- c("dynpv", class(df))
return(df)
}

# Function if uptakes, payoffs, prices and discounting are functions
dynpv_fullycts <- function(uptakes, payoffs, horizon, tzero, prices, discrate){
# First integrand function - pRv, to be integrated between k=0 and k=T-j
integrand1 <- function(k, j) {
payoffs(k) * prices(j+k+tzero) * discrate(j+k)
}
# Second integrand function, uj I, to be integrated between j=0 and j=T
integrand2 <- function(j) {
pRv <- stats::integrate(integrand1, lower=0, upper=horizon-j, j=j)$value
uptakes(j) * pRv
}
# Needs to be vectorized before integrating
integrand2 <- Vectorize(integrand2, "j")
# Calculate double integral
df <- stats::integrate(integrand2, lower=0, upper=horizon)
return(df$value)
}
11 changes: 2 additions & 9 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Through the [dynpv()](https://msdllcpapers.github.io/dynamicpv/reference/dynpv.h

## Installation

The package should shortly be available on [CRAN](https://cran.r-project.org/web/packages/index.html). Installing from here is simplest, once available.
The package is now available on [CRAN](https://cran.r-project.org/web/packages/index.html). Installing from here is simplest, as follows.

```{r inst_cran}
#| eval: false
Expand All @@ -48,14 +48,7 @@ install.packages("devtools")
pak::pak("MSDLLCpapers/dynamicpv")
```

Note that the above does not install vignettes. Vignettes may be viewed on the [package website](https://msdllcpapers.github.io/dynamicpv/) or by instead running the following.

```{r instal2}
#| eval: false
devtools::install_github("MSDLLCpapers/dynamicpv", build_vignettes=TRUE)
```

You should then load the package, alongside some other packages used here.
Installing the development version in this way does not include vignettes. Vignettes may be viewed on the [package website](https://msdllcpapers.github.io/dynamicpv/). You can then load the package, alongside other packages you may find helpful.

```{r instal3}
#| eval: false
Expand Down
18 changes: 6 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ cost-effectiveness model, such as one computed using the

## Installation

The package should shortly be available on
The package is now available on
[CRAN](https://cran.r-project.org/web/packages/index.html). Installing
from here is simplest, once available.
from here is simplest, as follows.

``` r
# CRAN installation - when available
Expand All @@ -56,16 +56,10 @@ install.packages("devtools")
pak::pak("MSDLLCpapers/dynamicpv")
```

Note that the above does not install vignettes. Vignettes may be viewed
on the [package website](https://msdllcpapers.github.io/dynamicpv/) or
by instead running the following.

``` r
devtools::install_github("MSDLLCpapers/dynamicpv", build_vignettes=TRUE)
```

You should then load the package, alongside some other packages used
here.
Installing the development version in this way does not include
vignettes. Vignettes may be viewed on the [package
website](https://msdllcpapers.github.io/dynamicpv/). You can then load
the package, alongside other packages you may find helpful.

``` r
# Load the dynamicpv package
Expand Down
6 changes: 6 additions & 0 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Resubmission
This is a resubmission. In this version I have:

* Extended the description text in DESCRIPTION
* Revised the vignettes

## R CMD check results

0 errors | 0 warnings | 1 note
Expand Down
15 changes: 15 additions & 0 deletions tests/testthat/test-fullycts.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Test new fullycts calculations

# Example
payoffs <- function(t) {100+50*t}
prices <- function(t) {1.03 ^ (floor(t))}
discrate <- function(t) {0.97 ^ t}
uptakes <- function(t) {exp(-t/2)}

# 1. Full function calls intermediate function ok
test_that("Full function calls intermediate function ok", {
int <- dynpv_fullycts(uptakes=uptakes, payoffs=payoffs, horizon=5, tzero=0, prices=prices, discrate=discrate)
full <- dynpv(uptakes=uptakes, payoffs=payoffs, horizon=5, prices=prices, discrate=discrate)
expect_equal(int, full)
}
)
19 changes: 19 additions & 0 deletions tests/testthat/test-semicts.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Test new semicts calculations

# Example
payoffs <- function(t) {100+50*t}
prices <- function(t) {1.03 ^ (floor(t))}
discrate <- function(t) {0.97 ^ t}

# 1. Full function calls intermediate function ok
test_that("Full function calls intermediate function ok", {
int <- dynpv_semicts(uptakes=1, payoffs=payoffs, horizon=5, tzero=0, prices=prices, discrate=discrate)
full <- dynpv(payoffs=payoffs, horizon=5, prices=prices, discrate=discrate)
expect_equal(int, full)
}
)





Loading