survminer turns survival analysis output into publication ready ggplot2 figures
Survival Analysis and Visualization
At a glance
- What is it?
- survminer is an R package that wraps the survival package's fitting and testing functions in ggplot2 graphics, adding number at risk tables, forest plots, proportional hazards diagnostics, restricted mean survival time and competing risk curves. It suits an analyst preparing survival figures for a paper, and it is a plotting layer rather than a new statistical method.
- Who is it for?
- Adopt survminer when you are producing survival analysis figures in R and want the risk tables, confidence bands and diagnostics that reviewers expect without assembling them by hand. Skip it if you need a new statistical method, since the package supplies graphics and effect measures around the survival package rather than new estimation techniques.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 86 days ago.
- What is it written in?
- Mainly R, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The package is a graphics layer over the survival package, not a new method
The survminer R package provides functions for facilitating survival analysis and visualization, and the main functions are organised in categories. Understanding that it is a graphics and reporting layer is the key to using it well. The statistical machinery comes from the survival package, and survminer's job is to take the objects that package produces and render them. The ggsurvplot function draws survival curves with the number at risk table, the cumulative number of events table and the cumulative number of censored subjects table, which are the three tables a survival figure is normally expected to carry and which are tedious to build by hand. The install is a single line from CRAN, and the package is also documented at rpkgs.datanovia.com/survminer with usage examples for each function.
Installing from CRAN or from GitHub, then loading the package
The installation section gives both routes. From CRAN it is one call:
install.packages("survminer")And for the latest version straight from GitHub, which needs devtools and builds the vignettes:
if(!require(devtools)) install.packages("devtools")
devtools::install_github("kassambara/survminer", build_vignettes = FALSE)The package is then loaded the usual way:
library("survminer")The devtools route with build_vignettes set to FALSE is the practical one for a CI environment, because building the vignettes means running every example in the documentation, which is slow and is one more thing to break. The package is on CRAN with a version badge and a download badge, and the repository carries the usual R package layout with a DESCRIPTION file, a NAMESPACE, an R/ directory of source, man/ of documentation, tests/, vignettes/, and a pkgdown/ directory for the site. The primary language is R and the default branch is master.
The example pipeline is fit first, then plot
The usage pattern separates fitting from drawing, which is the right way round. You fit with the survival package, and you plot with survminer:
require("survival")
fit <- survfit(Surv(time, status) ~ sex, data = lung)ggsurvplot(fit, data = lung)The plot function takes the fit object plus the data frame, and the data argument is there so the risk table can be computed at each time point. The censoring marks are adjustable, and the next example changes the censor shape and size:
ggsurvplot(fit, data = lung, censor.shape="|", censor.size = 4)Beyond the basics the argument list is where most of the work happens. The customised example shows size for line width, a palette argument for the group colours, conf.int to add the confidence interval, pval to put the p-value on the figure, risk.table to add the risk table, risk.table.col set to strata so the table is coloured by group, legend.labs for the legend text, risk.table.height for the table height when there are several groups, and ggtheme to change the ggplot2 theme. The cumulative hazard of forgetting one of these is a figure that looks fine until a reader notices the risk table is missing.
The modern effect measures fill a gap in the older toolkit
Three function groups address statistical questions that a plain Kaplan-Meier plot does not answer. The restricted mean survival time functions, ggrmst and ggrmst_difference, shade the area under the curve to a horizon called tau and annotate the between-arm difference with its confidence interval and p-value, which is the modern alternative to reading a median off a curve when the curves do not cross. The landmark function, gglandmark, re-origins the survival curves at a landmark time, and the reason given is to avoid immortal-time, also called guarantee-time, bias, which is the classic trap in a design where treatment is assigned based on survival. The milestone function, ggmilestone, reports survival at one or more fixed timepoints with the between-arm difference, confidence interval and p-value. The survival curve functions around them include ggsurvevents for the distribution of event times, ggsurvparametric to overlay a parametric fit such as survreg or flexsurv on the Kaplan-Meier curves, surv_summary, surv_cutpoint for the optimal cutpoint of one or more continuous variables, surv_median_followup for the median follow-up time by the reverse Kaplan-Meier method, pairwise_survdiff for multiple comparisons with corrections for multiple testing, and weighted_logrank for the weighted Fleming-Harrington log-rank test with arbitrary early or late emphasis.
Cox model diagnostics, summaries and competing risks each get their own plot
The diagnostics of the Cox model are a category of their own, and they are the ones that catch a broken model rather than a broken figure. ggcoxzph is the graphical test of proportional hazards, displaying a graph of the scaled Schoenfeld residuals along with a smooth curve using ggplot2, and it wraps plot.cox.zph. ggcoxfunctional shows continuous explanatory variables against martingale residuals of the null Cox model, and its stated purpose is to help properly choose the functional form of a continuous variable in a Cox model. ggcoxnph is a non-proportional-hazards diagnostic panel with cloglog, scaled Schoenfeld with a time-varying-coefficient smooth, a hazard-ratio trend and an RMST difference, which is what you reach for when the proportional hazards assumption does not hold. The summary functions draw on the same fitted model, with ggforest drawing a forest plot for the Cox proportional hazards model, ggforest_models comparing one covariate's hazard ratio across several Cox models, crude against adjusted, and ggforest_subgroup giving the treatment hazard ratio within each subgroup with the interaction effect-modification p-value. ggadjustedcurves plots adjusted survival curves for the coxph model, and ggcompetingrisks plots cumulative incidence curves for competing risks.
A clinical trial data helper handles the censoring flag convention
One function stands apart because it deals with data preparation rather than graphics. surv_adtte prepares a CDISC ADaM time-to-event dataset, the ADTTE dataset, for analysis, and it derives the event indicator from the CNSR flag. The reason the documentation gives is worth noting, because it is the kind of detail that silently changes results: it avoids the silent censoring-flag inversion, since in the CDISC convention the CNSR variable holds the censoring indicator rather than the event indicator, and a pipeline that inverts it without noticing produces an analysis that is confidently wrong. The rest of the package is focused on figures, and the documentation for each function is published with usage examples at the package site. The maintenance picture is that the repository is not archived with the last push on 2026-07-30, the recent releases are v0.5.2 from 2026-02-25, v0.5.1 from 2025-09-03 and v0.5.0 from 2024-10-30, and the licence field in the repository metadata is recorded as unknown even though the package is distributed on CRAN under a standard licence.
Where survminer is the wrong choice
Three situations argue against it. The first is a project that needs a new statistical method. survminer supplies graphics and a set of modern effect measures around the existing survival package, so if your question is how to model a time-dependent covariate or how to handle interval censoring, you will not find the estimator here and you need a different package. The second is a workflow that has moved to Python. The ecosystem in Python for survival analysis is a separate world, and the ggplot2 idiom that makes survminer pleasant, a data frame in, a publication figure out, has no direct equivalent, so adopting it means staying in R for that part of the analysis. The third is a publication with a strict house style. Because the output is ggplot2, the theme and element control is good, but the specific tables, the risk table position and the annotation layout are survminer's, and a journal that expects a particular format will need work after the fact. The realistic alternative for a team that wants the same figures with different defaults is to write the ggplot2 calls yourself against the survfit object, which is more work per figure but gives complete control, and the package remains the fastest way to see what a good survival figure contains before you rebuild it.
Editorial conclusion
Adopt survminer when you are producing survival analysis figures in R and want the risk tables, confidence bands and diagnostics that reviewers expect without assembling them by hand. Skip it if you need a new statistical method, since the package supplies graphics and effect measures around the survival package rather than new estimation techniques. Verify first that your R version and the survival package version you rely on are compatible with the survminer release you install, and check whether the functions you need are in the current release or still listed as planned.
Frequently asked questions
What is the survminer R package?
It provides functions for facilitating survival analysis and visualization, organising its main functions into categories for survival curves, modern effect measures, Cox model diagnostics, Cox model summaries, competing risks and clinical trial data. The site is rpkgs.datanovia.com/survminer with usage examples for each function.
How do I install survminer?
Install it from CRAN with install.packages("survminer"), or install the latest version from GitHub with devtools::install_github("kassambara/survminer", build_vignettes = FALSE), then load it with library("survminer").
What does ggsurvplot draw?
It draws survival curves with the number at risk table, the cumulative number of events table and the cumulative number of censored subjects table. Arguments cover line size, a custom colour palette, confidence interval, p-value, risk table, risk table colour by strata, legend labels, risk table height and the ggplot2 theme.
What are the modern effect measures in survminer?
Restricted mean survival time through ggrmst and ggrmst_difference, which shade the area to a horizon tau and annotate the between-arm difference, landmark analysis through gglandmark, which re-origins the curves to avoid immortal time bias, and milestone analysis through ggmilestone for fixed-time survival with differences, confidence intervals and p-values.
Is survminer still maintained?
The repository is not archived and the last push was on 2026-07-30, with releases v0.5.2 from 2026-02-25, v0.5.1 from 2025-09-03 and v0.5.0 from 2024-10-30. The package is on CRAN and the licence field in the repository metadata is recorded as unknown, so the terms are worth confirming directly.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kassambara-survminer)Was this useful?