Skip to content

Commit be1107b

Browse files
author
shstat1729
committed
Adding
1 parent ddede3a commit be1107b

25 files changed

+1957
-1
lines changed

.Rbuildignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
^\.github$
2+
^\.github/
3+
^\.gitignore$
4+
^\.Rprofile$
5+
^LICENSE\.md$
6+
^renv$
7+
^renv/
8+
^renv\.lock$

.Rprofile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if (file.exists("renv/activate.R")) {
2+
source("renv/activate.R")
3+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
on:
2+
push:
3+
branches: [main]
4+
pull_request:
5+
6+
name: check-latest
7+
8+
permissions: read-all
9+
10+
jobs:
11+
R-CMD-check:
12+
runs-on: ${{ matrix.config.os }}
13+
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
config:
18+
- {os: macos-latest, r: "release"}
19+
- {os: windows-latest, r: "release"}
20+
- {os: ubuntu-latest, r: "devel", http-user-agent: "release"}
21+
- {os: ubuntu-latest, r: "release"}
22+
- {os: ubuntu-latest, r: "oldrel-1"}
23+
24+
env:
25+
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
26+
R_KEEP_PKG_SOURCE: yes
27+
28+
steps:
29+
- uses: actions/checkout@v5
30+
31+
- uses: r-lib/actions/setup-pandoc@v2
32+
33+
- uses: r-lib/actions/setup-r@v2
34+
with:
35+
r-version: ${{ matrix.config.r }}
36+
http-user-agent: ${{ matrix.config.http-user-agent }}
37+
use-public-rspm: true
38+
39+
- uses: r-lib/actions/setup-r-dependencies@v2
40+
with:
41+
extra-packages: any::rcmdcheck
42+
needs: check
43+
44+
- uses: r-lib/actions/check-r-package@v2
45+
with:
46+
upload-snapshots: true
47+
build_args: 'c("--no-manual", "--compact-vignettes=gs+qpdf")'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
on:
2+
push:
3+
branches: [main]
4+
pull_request:
5+
6+
name: check-reproducible
7+
8+
permissions: read-all
9+
10+
jobs:
11+
R-CMD-check-renv:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v5
16+
17+
- uses: r-lib/actions/setup-pandoc@v2
18+
19+
- uses: r-lib/actions/setup-r@v2
20+
with:
21+
r-version: "4.4.2"
22+
23+
- uses: r-lib/actions/setup-renv@v2
24+
25+
- uses: r-lib/actions/check-r-package@v2
26+
with:
27+
build_args: 'c("--no-manual")'

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.Rhistory
2+
.RData
3+
.Ruserdata
4+
.Rproj.user/
5+
*.Rproj
6+
/*.tar.gz
7+
/*.Rcheck/
8+
inst/doc
9+
renv/library/
10+
renv/python/
11+
renv/staging/
12+
src/*.o
13+
src/*.so
14+
src/*.dll
15+
src/*.dylib

DESCRIPTION

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Package: clonecensorweighting
2+
Title: Infrastructure for Clone-Censor-Weighting Analyses
3+
Version: 0.0.0.9000
4+
Authors@R:
5+
person("Sang Ho", "Park", email = "shstat1729@gmail.com", role = c("aut", "cre"))
6+
Description: Provides a starter package for clone-censor-weighting workflows
7+
used in target trial emulation. The package currently includes data
8+
ingestion helpers, a minimal data cloning routine, and utilities for
9+
constructing survival responses.
10+
License: MIT + file LICENSE
11+
Encoding: UTF-8
12+
Depends:
13+
R (>= 4.4.0)
14+
Imports:
15+
dplyr,
16+
purrr,
17+
readr,
18+
survival,
19+
tibble,
20+
tidyr
21+
Suggests:
22+
knitr,
23+
rmarkdown,
24+
testthat (>= 3.0.0)
25+
Config/testthat/edition: 3
26+
Roxygen: list(markdown = TRUE)
27+
RoxygenNote: 7.3.3

LICENSE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
YEAR: 2026
2+
COPYRIGHT HOLDER: Sang Ho Park

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# MIT License
2+
3+
Copyright (c) 2026 Sang Ho Park
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

NAMESPACE

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Generated by roxygen2: do not edit by hand
2+
3+
export(clone_censor_weighting)
4+
export(make_surv_response)
5+
export(read_trial_data)

R/clone_censor_weighting.R

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#' Create a starter clone-censor-weighting dataset
2+
#'
3+
#' Expands each observation into one row per treatment strategy and flags
4+
#' immediate deviations from the observed baseline treatment as censored clones.
5+
#' This is a light-weight scaffold for package development rather than a full
6+
#' causal inference implementation.
7+
#'
8+
#' @param data A data frame containing one row per participant.
9+
#' @param id The name of the participant identifier column.
10+
#' @param follow_up The name of the follow-up time column.
11+
#' @param event The name of the event indicator column.
12+
#' @param treatment The name of the observed treatment column.
13+
#' @param regimes Optional vector of treatment strategies to clone. When `NULL`,
14+
#' unique non-missing observed treatments are used.
15+
#'
16+
#' @return A tibble with one row per participant-strategy combination and the
17+
#' additional columns `.clone_id`, `.regime`, `.censored`, and `.weight`.
18+
#' @export
19+
clone_censor_weighting <- function(
20+
data,
21+
id,
22+
follow_up,
23+
event,
24+
treatment,
25+
regimes = NULL
26+
) {
27+
.assert_data_frame(data)
28+
29+
required_columns <- c(id, follow_up, event, treatment)
30+
.assert_required_columns(data, required_columns)
31+
32+
tbl <- tibble::as_tibble(data)
33+
34+
if (!is.numeric(tbl[[follow_up]])) {
35+
stop("`follow_up` must refer to a numeric column.", call. = FALSE)
36+
}
37+
38+
if (!all(stats::na.omit(tbl[[event]]) %in% c(0, 1))) {
39+
stop("`event` must contain only 0/1 values.", call. = FALSE)
40+
}
41+
42+
if (is.null(regimes)) {
43+
regimes <- sort(unique(stats::na.omit(tbl[[treatment]])))
44+
}
45+
46+
if (length(regimes) == 0) {
47+
stop("`regimes` must contain at least one treatment strategy.", call. = FALSE)
48+
}
49+
50+
id_values <- tbl[[id]]
51+
observed_treatment <- tidyr::replace_na(as.character(tbl[[treatment]]), ".missing")
52+
regime_values <- as.character(regimes)
53+
54+
clones <- purrr::map(
55+
regime_values,
56+
function(regime) {
57+
clone <- dplyr::mutate(
58+
tbl,
59+
.clone_id = paste(id_values, regime, sep = "::"),
60+
.regime = regime,
61+
.censored = as.integer(observed_treatment != regime),
62+
.weight = 1
63+
)
64+
65+
clone[, c(
66+
".clone_id",
67+
".regime",
68+
".censored",
69+
".weight",
70+
setdiff(names(clone), c(".clone_id", ".regime", ".censored", ".weight"))
71+
)]
72+
}
73+
)
74+
75+
cloned_tbl <- dplyr::bind_rows(clones)
76+
row_order <- order(cloned_tbl[[id]], cloned_tbl[[follow_up]], cloned_tbl[[".regime"]])
77+
78+
tibble::as_tibble(cloned_tbl[row_order, , drop = FALSE])
79+
}
80+
81+
#' Construct a survival response
82+
#'
83+
#' @param data A data frame with follow-up and event columns.
84+
#' @param follow_up The name of the follow-up time column.
85+
#' @param event The name of the event indicator column.
86+
#'
87+
#' @return An object of class `"Surv"`.
88+
#' @export
89+
make_surv_response <- function(data, follow_up, event) {
90+
.assert_data_frame(data)
91+
.assert_required_columns(data, c(follow_up, event))
92+
93+
survival::Surv(time = data[[follow_up]], event = data[[event]])
94+
}

0 commit comments

Comments
 (0)