Skip to content

Commit

Permalink
Merge pull request #24 from cyk0315/master
Browse files Browse the repository at this point in the history
theme JAMA , NEJM
  • Loading branch information
jinseob2kim authored Jan 26, 2024
2 parents 8839bea + dd023eb commit dcd22d6
Show file tree
Hide file tree
Showing 33 changed files with 276 additions and 96 deletions.
9 changes: 5 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
Package: jskm
Title: Kaplan-Meier Plot with 'ggplot2'
Version: 0.5.2
Date: 2023-08-04
Version: 0.5.3
Date: 2024-01-24
Authors@R: c(person("Jinseob", "Kim", email = "jinseob2kim@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-9403-605X")),
person("yoonkyoung", "Chun", email = "rachel200357@gmail.com"),
person("Zarathu", role = c("cph", "fnd"))
)
Description: The function 'jskm()' creates publication quality Kaplan-Meier plot with at risk tables below. 'svyjskm()' provides plot for weighted Kaplan-Meier estimator.
Depends: R (>= 3.4.0)
License: Apache License 2.0
Encoding: UTF-8
Imports: ggplot2, ggpubr, survival, survey, scales
RoxygenNote: 7.2.3
Imports: ggplot2, ggpubr, survival, survey, scales, patchwork
RoxygenNote: 7.3.1
URL: https://github.com/jinseob2kim/jskm
BugReports: https://github.com/jinseob2kim/jstable/issues
Suggests:
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ importFrom(ggplot2,xlab)
importFrom(ggplot2,ylab)
importFrom(ggpubr,ggarrange)
importFrom(grid,unit)
importFrom(patchwork,inset_element)
importFrom(stats,as.formula)
importFrom(stats,formula)
importFrom(stats,pchisq)
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# jskm 0.5.3

* Update: Add theme('JAMA','NEJM') to `jskm` and `svyjskm`

# jskm 0.5.2

* Update: Add `linewidth` option
Expand Down
102 changes: 71 additions & 31 deletions R/jskm.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#' @param showpercent Shows the percentages on the right side.
#' @param status.cmprsk Status value when competing risk analysis, Default = 2nd level of status variable
#' @param linewidth Line witdh, Default = 0.75
#' @param theme Theme of the plot, Default = NULL, "nejm" for NEJMOA style, "jama" for JAMA style
#' @param nejm.infigure.ratiow Ratio of infigure width to total width, Default = 0.6
#' @param nejm.infigure.ratioh Ratio of infigure height to total height, Default = 0.5
#' @param nejm.infigure.ylim y-axis limit of infigure, Default = c(0,1)
#' @param ... PARAM_DESCRIPTION
#' @return Plot
#' @details DETAILS
Expand Down Expand Up @@ -73,6 +77,7 @@
#' @importFrom grid unit
#' @importFrom ggpubr ggarrange
#' @importFrom stats pchisq time as.formula
#' @importFrom patchwork inset_element
#' @importFrom survival survfit survdiff coxph Surv cluster frailty
#' @export

Expand Down Expand Up @@ -110,6 +115,11 @@ jskm <- function(sfit,
showpercent = F,
status.cmprsk = NULL,
linewidth = 0.75,
theme=NULL,
nejm.infigure.ratiow=0.6,
nejm.infigure.ratioh=0.5,
nejm.infigure.ylim=c(0,1),

...) {
#################################
# sorting the use of subsetting #
Expand All @@ -118,7 +128,7 @@ jskm <- function(sfit,
n.risk <- n.censor <- surv <- strata <- lower <- upper <- NULL

times <- seq(0, max(sfit$time), by = timeby)

if(!is.null(theme)&&theme=='nejm') legendposition<-'right'
if (is.null(subs)) {
if (length(levels(summary(sfit)$strata)) == 0) {
subs1 <- 1
Expand Down Expand Up @@ -148,43 +158,43 @@ jskm <- function(sfit,
subs2 <- which(regexpr(ssvar, summary(sfit, censored = T)$strata, perl = T) != -1)
subs3 <- which(regexpr(ssvar, summary(sfit, times = times, extend = TRUE)$strata, perl = T) != -1)
}

if (!is.null(subs) | !is.null(sfit$states)) pval <- FALSE

##################################
# data manipulation pre-plotting #
##################################

if (is.null(ylabs)) {
if (cumhaz | !is.null(sfit$states)) {
ylabs <- "Cumulative incidence"
} else {
ylabs <- "Survival probability"
}
}


if (length(levels(summary(sfit)$strata)) == 0) {
# [subs1]
if (is.null(ystratalabs)) ystratalabs <- as.character(sub("group=*", "", "All"))
} else {
# [subs1]
if (is.null(ystratalabs)) ystratalabs <- as.character(sub("group=*", "", names(sfit$strata)))
}

if (is.null(ystrataname)) ystrataname <- "Strata"
m <- max(nchar(ystratalabs))
times <- seq(0, max(sfit$time), by = timeby)

if (length(levels(summary(sfit)$strata)) == 0) {
Factor <- factor(rep("All", length(subs2)))
} else {
Factor <- factor(summary(sfit, censored = T)$strata[subs2], levels = names(sfit$strata))
}

# Data to be used in the survival plot


if (is.null(sfit$state)) { # no cmprsk
df <- data.frame(
time = sfit$time[subs2],
Expand Down Expand Up @@ -316,8 +326,8 @@ jskm <- function(sfit,
scale_labels <- ggplot2::waiver()
if (surv.scale == "percent") scale_labels <- scales::percent

p <- ggplot2::ggplot(df, aes(x = time, y = surv, colour = strata, linetype = strata)) +
ggtitle(main)
p <- ggplot2::ggplot(df, aes(x = time, y = surv, colour = strata, linetype = strata) ) + ggtitle(main)


linecols2 <- linecols
if (linecols == "black") {
Expand All @@ -333,19 +343,26 @@ jskm <- function(sfit,
axis.title.x = element_text(vjust = 0.7),
panel.grid.minor = element_blank(),
axis.line = element_line(linewidth = 0.5, colour = "black"),
legend.position = legendposition,
legend.background = element_rect(fill = NULL),
legend.position = legendposition,
legend.background = element_rect(fill = NULL),
legend.key = element_rect(colour = NA),
panel.border = element_blank(),
plot.margin = unit(c(0, 1, .5, ifelse(m < 10, 1.5, 2.5)), "lines"),
panel.grid.major = element_blank(),
axis.line.x = element_line(linewidth = 0.5, linetype = "solid", colour = "black"),
axis.line.y = element_line(linewidth = 0.5, linetype = "solid", colour = "black")
) +
scale_x_continuous(xlabs, breaks = times, limits = xlims) +
scale_y_continuous(ylabs, limits = ylims, labels = scale_labels)



if(!is.null(theme)&&theme=='jama'){
p<-p+theme(
panel.grid.major.x = element_blank()
)
} else{
p <- p + theme(
panel.grid.major = element_blank()
)}


# Removes the legend:
if (legend == FALSE) {
Expand All @@ -355,13 +372,18 @@ jskm <- function(sfit,
# Add lines too plot
if (is.null(cut.landmark)) {
p <- p + geom_step(linewidth = linewidth) +
scale_linetype_manual(name = ystrataname, values = linetype) +
scale_colour_brewer(name = ystrataname, palette = linecols)
scale_linetype_manual(name = ystrataname, values = linetype)
} else {
p <- p +
scale_linetype_manual(name = ystrataname, values = linetype) +
geom_step(data = subset(df, time >= cut.landmark), linewidth = linewidth) + geom_step(data = subset(df, time < cut.landmark), linewidth = linewidth) +
scale_colour_brewer(name = ystrataname, palette = linecols)
geom_step(data = subset(df, time >= cut.landmark), linewidth = linewidth) + geom_step(data = subset(df, time < cut.landmark), linewidth = linewidth)
}

if(!is.null(theme)&&theme=='jama'){
p<-p+scale_color_manual(name=ystrataname, values = c("#00AFBB", "#E7B800", "#FC4E07"))
}else{
p<-p+ scale_colour_brewer(name = ystrataname, palette = linecols)

}


Expand All @@ -382,7 +404,7 @@ jskm <- function(sfit,
if (!is.null(cut.landmark)) {
p <- p + geom_vline(xintercept = cut.landmark, lty = 2)
}

p1<-p
if (showpercent == T) {
if (is.null(cut.landmark)) {
y.percent <- summary(sfit, times = xlims[2], extend = T)$surv
Expand All @@ -391,7 +413,11 @@ jskm <- function(sfit,
}
if (cumhaz == T & is.null(sfit$states)) y.percent <- 1 - y.percent
p <- p + annotate(geom = "text", x = xlims[2], y = y.percent, label = paste0(round(100 * y.percent, 1), "%"), color = "black")
} else {
if(!is.null(theme)&&theme == 'nejm') {
p1 <- p1 + annotate(geom = "text", x = xlims[2], y = y.percent, label = paste0(round(100 * y.percent, 1), "%"), color = "black",size=nejm.infigure.ratiow*5)

}
} else {
y.percent1 <- summary(sfit, times = cut.landmark, extend = T)$surv
y.percent2 <- summary(sfit2, times = xlims[2], extend = T)$surv
if (!is.null(sfit$states)) {
Expand All @@ -404,7 +430,12 @@ jskm <- function(sfit,
}
p <- p + annotate(geom = "text", x = cut.landmark, y = y.percent1, label = paste0(round(100 * y.percent1, 1), "%"), color = "black") +
annotate(geom = "text", x = xlims[2], y = y.percent2, label = paste0(round(100 * y.percent2, 1), "%"), color = "black")
}
if(!is.null(theme)&&theme == 'nejm') {
p1 <- p1 + annotate(geom = "text", x = cut.landmark, y = y.percent1, label = paste0(round(100 * y.percent1, 1), "%"), color = "black",size=nejm.infigure.ratiow*5) +
annotate(geom = "text", x = xlims[2], y = y.percent2, label = paste0(round(100 * y.percent2, 1), "%"), color = "black",size=nejm.infigure.ratiow*5)

}
}
}


Expand All @@ -425,7 +456,7 @@ jskm <- function(sfit,

if (length(levels(summary(sfit)$strata)) == 0) pval <- F
# if(!is.null(cut.landmark)) pval <- F

if (pval == TRUE) {
if (is.null(data)) {
data <- tryCatch(eval(sfit$call$data), error = function(e) e)
Expand Down Expand Up @@ -453,7 +484,7 @@ jskm <- function(sfit,

pvaltxt <- ifelse(pvalue < 0.001, "p < 0.001", paste("p =", round(pvalue, 3)))
if (pval.testname) pvaltxt <- paste0(pvaltxt, " (Log-rank)")

# MOVE P-VALUE LEGEND HERE BELOW [set x and y]
if (is.null(pval.coord)) {
p <- p + annotate("text", x = (as.integer(max(sfit$time) / 5)), y = 0.1 + ylims[1], label = pvaltxt, size = pval.size)
Expand Down Expand Up @@ -489,7 +520,7 @@ jskm <- function(sfit,
pvaltxt <- ifelse(pvalue < 0.001, "p < 0.001", paste("p =", round(pvalue, 3)))

if (pval.testname) pvaltxt <- paste0(pvaltxt, " (Log-rank)")

if (is.null(pval.coord)) {
p <- p + annotate("text", x = c(as.integer(max(sfit$time) / 10), as.integer(max(sfit$time) / 10) + cut.landmark), y = 0.1 + ylims[1], label = pvaltxt, size = pval.size)
} else {
Expand Down Expand Up @@ -545,13 +576,22 @@ jskm <- function(sfit,
#######################
# Plotting the graphs #
#######################


if(!is.null(theme)&&theme == 'nejm') {
p2<-p1+coord_cartesian(ylim=nejm.infigure.ylim)+theme(legend.position='none',axis.title.x = element_blank(),axis.title.y=element_blank(),
axis.text= element_text(size=10*nejm.infigure.ratiow))
p<- p + patchwork::inset_element(p2, 1-nejm.infigure.ratiow,1-nejm.infigure.ratioh, 1, 1,align_to = 'panel')
}

if (table == TRUE) {
ggpubr::ggarrange(p, blank.pic, data.table,
nrow = 3, align = "v",
nrow = 3,
#align = "v",
heights = c(2, .1, .25)
)
} else {
p
p
}
}


Loading

0 comments on commit dcd22d6

Please sign in to comment.