Author: Wenchuan Guo and Bob Zhong
Date: 2026-04-25

# Quick Start Guide

#### Wenchuan Guo and Bob Zhong

#### 2026-04-25

This guide introduces the basic workflow of `tsdf`. For additional details, see the documentation for individual functions.

## Installation

Install the package from R with:

    install.packages("tsdf")

Then load the package:

    library(tsdf)

The remaining sections give short examples of the main functions.

## Zhong’s 2-/3-stage Phase II designs

To calculate Zhong’s two- or three-stage design, specify the left-side type I error (`alpha1`), right-side type I error (`alpha2`), type II error (`beta`), minimal response rate (`pc`), and postulated response rate (`pe`). The `stage` argument should be set to `2` or `3`.

The following example computes a two-stage design:

    # type I errors
    alpha1 <- 0.15
    alpha2 <- 0.10

    # type II error
    beta <- 0.15

    # response rates
    pc <- 0.25
    pe <- pc + 0.20

    # two-stage design
    out <- opt.design(alpha1, alpha2, beta, pc, pe, stage = 2)

`out` is an object of class `opt.design`. The `print` method shows the recommended design and its operating characteristics:

    print(out)

    ##
    ##  Zhong's 2 stage Phase II design
    ##
    ## Minimal response rate:  0.45
    ## Postulate response rate:
    ## Left-side type 1 error:  0.15
    ## Right-side type 1 error:  0.1
    ## Type 2 error:  0.15
    ##
    ## Notation:
    ## Left-side rejection region at stage i is response <= ri
    ## Right-side rejection region at stage 2 is response > s
    ## Sample size used at stage i is ni
    ##
    ## Optimal design :
    ## r1 r2 s1 s2 n1 n2
    ##  0  4  9 11  9 24
    ## True errors :
    ## alpha11 alpha12 alpha21 alpha22    beta
    ##  0.0751  0.1152  0.0000  0.0982  0.1217

Alpha-spending methods are available for both two- and three-stage designs. `opt.design()` uses the Hwang-Shih-DeCani spending function, with `sf.param` controlling the shape of the spending rule. For two-stage designs, the default is `NULL`, which means no alpha-spending is used. For three-stage designs, the default is `4`. For example, to use a Pocock-like spending function, set `sf.param = 1`:

    opt.design(alpha1, alpha2, beta, pc, pe, stage = 2, sf.param = 1)

## Decision table for Phase I dose-finding

`dec.table()` generates a decision table for a three-stage dose-finding design. `alpha.l` (left side), `alpha.r` (right side), and `alpha.u` (right-side type I error for `"DU"`, usually smaller than `alpha.r`) control the decision boundaries. `pt` is the target toxicity level and may be given as either a single value or an interval.

This procedure also supports alpha-spending through the `sf.param` argument, which has the same interpretation as in `opt.design()`. The default is `4`.

    # cohort sizes at each stage
    n <- rep(3, 3)

    # type I errors
    alpha.l <- 0.6
    alpha.r <- 0.4
    alpha.u <- 0.2

    # target toxicity
    pt <- 0.3

    # generate the decision table
    out <- dec.table(alpha.l, alpha.r, alpha.u, pt, n)

`out` is an object of class `dec.table` that contains the decision table, realized error rates, and input settings. In most cases, it is better to use the provided S3 methods than to extract components manually.

View the decision table with:

    print(out)

    ##   3  6  9
    ## 0 E  E  E
    ## 1 S  E  E
    ## 2 D  S  E
    ## 3 DU D  S
    ## 4 0  DU D
    ## 5 0  DU DU
    ## 6 0  DU DU
    ## 7 0  0  DU
    ## 8 0  0  DU
    ## 9 0  0  DU
    ##
    ##    Row : Number of DLTs
    ## Column : Number of subjects
    ##      E : Escalate to the next higher dose
    ##      S : Stay at the same dose
    ##      D : De-escalate to the previous lower dose
    ##     DU : De-escalate and never use this dose again
    ##
    ## Type 1 error :
    ##   alpha11   alpha12   alpha13   alpha21   alpha22   alpha23
    ## 0.3430000 0.4942630 0.5609700 0.2160000 0.3112560 0.3532639
    ## Type 2 error :  0.1690468
    ## Right-side type 1 error :
    ##   alpha11   alpha12   alpha13
    ## 0.0270000 0.0797310 0.1264898

Plot the decision boundaries with:

    plot(out)

## Dose-finding simulations

`dec.sim()` and `sl.sim()` run dose-finding simulations from a user-supplied decision table. To run a simulation, provide a decision table, the true toxicity probabilities for each dose level, the starting dose level (default: the lowest dose), and the number of simulated trials (default: `1000`).

`dec.sim()` runs a single scenario. `sl.sim()` runs a list of scenarios stored in a `.csv` or `.txt` file.

The simulation functions expect the decision table to be a matrix- or data-frame-like object with sample sizes as column names. If you start from `dec.table()`, convert `out$table` before passing it to the simulation functions:

    # true toxicity probabilities
    truep <- c(0.3, 0.45, 0.5, 0.6)

    # generate a decision table
    dt <- dec.table(0.6, 0.4, 0.2, 0.3, c(3, 3, 3))

    # convert the table object to a plain matrix for simulation
    sim_table <- matrix(
      as.character(dt$table),
      nrow = nrow(dt$table),
      dimnames = dimnames(dt$table)
    )

    # run one simulation scenario
    out1 <- dec.sim(truep, sim_table, start.level = 2, nsim = 1000)

The package also includes a sample scenario list:

    test.file <- system.file("extdata", "testS.csv", package = "tsdf")

Run simulations across all scenarios with:

    out2 <- sl.sim(sim_table, test.file)

`out1` is an object of class `dec.sim`. When the scenario file contains more than one scenario, `out2` has class `c("sl.sim", "dec.sim")`. Summary and plot methods are available for these objects. For example, the following command reports commonly used summary statistics:

    # target toxicity for each scenario
    pt <- c(0.3, 0.4)
    summary(out2, pt)

    ## What does each column represent ?
    ##
    ## Level : Dose level
    ## Truth : True toxicity probability
    ## MTD   : The probability of selecting current dose level as the MTD
    ## Over  : The probability of selecting current dose level as over the MTD
    ## DLT   : The average number of subjects experienced DLT at current dose level
    ## NP    : The average number of subjects treated at current dose level
    ##
    ## Scenario  1
    ##
    ## Simulation results are based on 1000 simulated trials
    ## Starting dose level is 1 ; MTD is dose 1
    ## Target toxicity probability = 0.3
    ## Average number of subjects = 10.557
    ## Probability of selecting the true MTD = 0.448
    ## Probability of subjects treated at or below the true MTD = 0.6152316
    ##
    ##   Level Truth   MTD  Over   DLT    NP
    ## 1     1  0.30 0.448 0.389 1.962 6.495
    ## 2     2  0.45 0.134 0.837 1.378 3.084
    ## 3     3  0.50 0.026 0.971 0.418 0.849
    ## 4     4  0.60 0.001 1.000 0.075 0.129
    ##
    ## Scenario  2
    ##
    ## Simulation results are based on 2000 simulated trials
    ## Starting dose level is 2 ; MTD is dose 3
    ## Target toxicity probability = 0.4
    ## Average number of subjects = 15.57
    ## Probability of selecting the true MTD = 0.6595
    ## Probability of subjects treated at or below the true MTD = 0.8149326
    ##
    ##   Level Truth    MTD   Over    DLT     NP
    ## 1     1  0.01 0.0365 0.0000 0.0025 0.3165
    ## 2     2  0.10 0.2710 0.0365 0.4975 5.1120
    ## 3     3  0.25 0.6595 0.3075 1.7985 7.2600
    ## 4     4  0.65 0.0305 0.9670 1.7460 2.7255
    ## 5     5  0.70 0.0005 1.0000 0.1125 0.1560

There are four plot types for a `dec.sim` object. The `s` argument selects the scenario to display, and `pt` gives the target toxicity for each scenario. See `?plot.dec.sim` for details:

    # scenario information (true toxicity)
    plot(out2, s = 2, pt = c(0.3, 0.4), type = "s")

    # probability of selecting each dose as the MTD
    plot(out2, s = 2, pt = c(0.3, 0.4), type = "prob")

    # average number of patients treated at each dose
    plot(out2, s = 2, pt = c(0.3, 0.4), type = "np")

    # average number of DLTs at each dose
    plot(out2, s = 2, pt = c(0.3, 0.4), type = "dlt")

To display all plot types in a single figure, run:

    plot(out2, pt = c(0.3, 0.4), type = "all", cex = 0.7)

## Scenario list and customized table format

The `.csv` or `.txt` files used by `sl.sim()` look like this:

Start.Dose | N.Trials | Dose1 | Dose2 | Dose3 | Dose4 | Dose5
--- | --- | --- | --- | --- | --- | ---
1 | 1000 | 0.30 | 0.45 | 0.50 | 0.60 | NA
2 | 2000 | 0.01 | 0.10 | 0.25 | 0.65 | 0.7

This example is stored in `inst/extdata/testS.csv` and can be located with `system.file()`. The file should include:

- `Start Dose`: the starting dose level.
- `N Trials`: the number of simulated trials.
- `Dose*`: the true toxicity probability at each dose level.

If scenarios contain different numbers of dose levels, the raw file does not need explicit `NA` values; blank cells are sufficient.

Both `dec.sim()` and `sl.sim()` also support user-supplied decision tables. The table can be a `matrix`, `data.frame`, or similar rectangular object in R. The user is responsible for ensuring that the table is a valid dose-finding decision table. In particular, the column names should be the actual cumulative sample sizes rather than the default names created by `read.table()`, such as `X.*` or `V.*`.

For example, the following code reads the sample decision table included in the package:

    table.file <- system.file("extdata", "decTable.csv", package = "tsdf")
    dec <- read.csv(table.file, row.names = 1, check.names = FALSE)
    colnames(dec)

    ## [1] "3"  "4"  "8"  "10"

After importing the table, it should have the following format:

| 3 | 4 | 8 | 10
--- | --- | --- | --- | ---
0 | E | E | E | E
1 | S | S | E | E
2 | D | D | S | E
3 | DU | DU | D | S
4 |  | DU | D | D
5 |  |  | DU | D
6 |  |  | DU | DU
7 |  |  | DU | DU
8 |  |  | DU | DU
9 |  |  |  | DU
10 |  |  |  | DU