Source: https://github.com/aipoch/medical-research-skills
Kaplan-Meier Survival Curve Analysis
Use this skill to run Kaplan-Meier survival analysis on a tabular dataset and export a single PDF survival figure.
Use This Skill When
- You need a Kaplan-Meier survival curve from a table containing time, status, and group columns.
- You need a command-line survival workflow with parameter validation.
- You need a single Kaplan-Meier plot as the final analysis result.
Primary Command
Rscript scripts/main.R \
--input_file <input_file> \
--output_dir <output_dir> \
--time_col <time_column> \
--status_col <status_column> \
--risk_col <group_column>
Prerequisites
Rscript is available in the shell.
- Required R packages:
optparse, data.table, survival, survminer, ggplot2.
- Install missing packages with
Rscript -e 'install.packages(c("optparse", "data.table", "survival", "survminer", "ggplot2"), repos="https://cloud.r-project.org")'.
Core Arguments
| Argument |
Required |
Description |
--input_file |
Yes |
Input data file in CSV or tab-delimited TXT/TSV format |
--output_dir |
No |
Output directory, default ./KM_Results |
--time_col |
No |
Survival time column, default futime |
--status_col |
No |
Event status column, default fustat |
--risk_col |
No |
Risk group column, default risk_group |
--time_unit |
No |
Time unit label: year, month, or day, default year |
--auto_convert_days |
No |
Heuristically convert large time values from days when time_unit is year or month, default true |
--statistics_method |
No |
logrank or wald, default logrank |
Plot Customization Arguments
| Argument |
Default |
Description |
--figure_width |
10 |
Figure width in inches |
--figure_height |
7 |
Figure height in inches |
--figure_family |
sans |
Font family |
--title_x |
Time |
X-axis title. If left as default, the script renders Time (<time_unit>) |
--title_y |
Survival probability |
Y-axis title |
--title_main |
empty |
Plot title |
--legend_position |
top |
top, bottom, left, right, none |
--legend_show |
true |
Whether to show legend |
--legend_title |
empty |
Legend title |
--line_type |
solid |
Survival line type: solid, dashed, dotted, dotdash, longdash, twodash |
--line_size |
1 |
Survival line width |
--line_colors |
#4DBBD5,#E64B35,#00A087,#3C5488,#F39B7F,#8491B4,#91D1C2,#DC0000 |
Comma-separated group colors |
--censor_show |
true |
Whether to show censor markers |
--censor_size |
7 |
Censor marker size |
--confidence_show |
true |
Whether to show confidence interval |
--confidence_alpha |
0.2 |
Confidence band transparency |
--risk_table_show |
true |
Whether to show the risk table |
--risk_table_border |
true |
Whether to show the risk table border |
--risk_table_panel |
false |
Whether to show the risk table panel background |
--risk_table_size |
6 |
Risk table font size |
--axis_title_size |
12 |
Axis title font size |
--axis_text_size |
10 |
Axis tick-label font size |
--legend_text_size |
11 |
Legend text font size |
Input Requirements
- The input file must contain the requested time, status, and group columns.
.txt inputs must be tab-delimited.
time must contain finite non-negative numeric values.
status must be coded as 0 for censored and 1 for event.
- The risk group column must be a precomputed categorical grouping variable, not a continuous score column.
- The risk group column must contain at least 2 groups after filtering.
--line_colors must provide at least one color per retained group when you override the default palette.
- Rows with missing time, status, or group values are removed before analysis.
- At least 2 complete observations must remain after filtering.
- Near-unique or continuous-looking grouping columns are rejected before model fitting.
- If
--auto_convert_days true and max(time) > 365, the script assumes the retained time values are in days and converts them to the requested --time_unit when time_unit is year or month.
- Only use
--auto_convert_days true when the source time column is known to be in days.
- If your source data are already in years or months, disable
--auto_convert_days to avoid incorrect conversion.
--statistics_method wald only supports exactly 2 retained groups; use logrank for multi-group comparisons.
- Invalid plotting parameters such as unsupported
--line_type values are rejected before plotting.
Example input:
id fustat futime risk_score risk_group GPR161 RIBC2
TCGA-C5-A1M5 1 5.62191780821918 -1.10702407761445 low 2.82521576230566 5.35318564979635
TCGA-VS-A94W 0 3.40547945205479 -0.671246677921865 high 4.26241812321536 4.00802068790173
Bundled test datasets:
tests/data/km_sample1.txt: baseline KM example with risk_group
tests/data/km_sample2.txt: alternate cohort for plotting and statistics examples
tests/data/km_sample3.txt: additional cohort for validation and repeated testing
Minimal Workflow
- Confirm the input file exists and identify the time, status, and group columns.
- Run
scripts/main.R with the requested output directory and any optional plot parameters.
- Check the output directory for
km-plot.pdf.
If you omit --input_file, the script exits with SKILL_MISSING_INPUT.
Outputs
Expected output:
<output_dir>/
├── km-plot.pdf
└── session_info.txt
Interpretation Guide
- Use the survival figure to inspect separation between groups over time.
- Use the p-value annotation, confidence interval, and risk table in the figure to interpret group separation.
Time Conversion Caution
- Automatic conversion is a convenience heuristic, not a unit detector.
- The script only checks whether
max(time) > 365; it does not infer the true source unit from metadata.
- If the input time column is already expressed in years or months, run with
--auto_convert_days false.
- Review the console log for the conversion warning whenever
time_unit is year or month.
Reproducibility Note
- Repeated runs on identical input should be analytically consistent.
- The exported
km-plot.pdf may not be byte-identical across repeated runs because PDF metadata and graphics-device output can vary.
- If you need byte-stable artifacts, add a deterministic PDF post-processing step outside this skill.
Do Not Use This Skill When
- You need this tool to derive a cutoff or split a continuous score into risk groups.
- You need multivariable Cox regression, covariate adjustment, or hazard-ratio modeling beyond the p-value route already exposed here.
- You need a broader survival-analysis workflow with upstream feature engineering, biomarker selection, or data harmonization.
- You need multiple plots, report generation, or downstream interpretation beyond producing one Kaplan-Meier figure and session metadata.
Read These Files When Needed
| Need |
File |
| Kaplan-Meier method details and interpretation |
references/algorithm.md |
| More CLI examples |
references/cli-guide.md |
| Error diagnosis |
references/troubleshooting.md |
| Main execution entry point |
scripts/main.R |
| Sample test data |
tests/data/km_sample1.txt, tests/data/km_sample2.txt, tests/data/km_sample3.txt |
Quick Examples
Basic Kaplan-Meier analysis:
Rscript scripts/main.R \
--input_file tests/data/km_sample1.txt \
--output_dir tests/output_basic
Custom column names:
Rscript scripts/main.R \
--input_file tests/data/km_sample1.txt \
--time_col futime \
--status_col fustat \
--risk_col risk_group \
--output_dir tests/output_custom_columns
Custom plot title:
Rscript scripts/main.R \
--input_file tests/data/km_sample2.txt \
--title_main "Study KM Curve" \
--output_dir tests/output_title
Hide confidence interval and risk table:
Rscript scripts/main.R \
--input_file tests/data/km_sample3.txt \
--confidence_show false \
--risk_table_show false \
--output_dir tests/output_simple
Validation
Rscript scripts/main.R --help
Rscript scripts/main.R \
--input_file tests/data/km_sample1.txt \
--output_dir tests/validation_output
After running analysis, verify that tests/validation_output/km-plot.pdf exists.
Common Errors
SKILL_FILE_NOT_FOUND: Input file path is wrong or inaccessible.
SKILL_MISSING_COLUMNS: A requested time, status, or risk group column is missing.
SKILL_INVALID_DATA: Input data is malformed or unsuitable for survival analysis.
SKILL_INVALID_DATA: A continuous or near-unique risk column was supplied where a categorical group column is required.
SKILL_INVALID_PARAMETER: An argument value is invalid.
SKILL_INVALID_PARAMETER: Plotting options such as --line_type or --line_colors are incompatible with the retained groups.
SKILL_INSUFFICIENT_DATA: Too few complete observations remain after filtering.
SKILL_DEPENDENCY_MISSING: A required R package such as optparse or survival is unavailable.
If the issue is not obvious, read references/troubleshooting.md.
1---2name: km-survival-curve3description: Use when generating Kaplan-Meier survival curves from tabular survival data containing time, event status, and a precomputed risk group. Supports command-line parameter input, parameter validation, automatic time-unit handling, single-file PDF figure export, and session metadata capture.4license: MIT5---6> **Source**: [https://github.com/aipoch/medical-research-skills](https://github.com/aipoch/medical-research-skills)
7
8# Kaplan-Meier Survival Curve Analysis
9
10Use this skill to run Kaplan-Meier survival analysis on a tabular dataset and export a single PDF survival figure.
11
12## Use This Skill When
13
14- You need a Kaplan-Meier survival curve from a table containing time, status, and group columns.
15- You need a command-line survival workflow with parameter validation.
16- You need a single Kaplan-Meier plot as the final analysis result.
17
18## Primary Command
19
20```bash
21Rscript scripts/main.R \
22 --input_file <input_file> \
23 --output_dir <output_dir> \
24 --time_col <time_column> \
25 --status_col <status_column> \
26 --risk_col <group_column>
27```
28
29## Prerequisites
30
31- `Rscript` is available in the shell.
32- Required R packages: `optparse`, `data.table`, `survival`, `survminer`, `ggplot2`.
33- Install missing packages with `Rscript -e 'install.packages(c("optparse", "data.table", "survival", "survminer", "ggplot2"), repos="https://cloud.r-project.org")'`.
34
35## Core Arguments
36
37| Argument | Required | Description |
38|----------|----------|-------------|
39| `--input_file` | Yes | Input data file in CSV or tab-delimited TXT/TSV format |
40| `--output_dir` | No | Output directory, default `./KM_Results` |
41| `--time_col` | No | Survival time column, default `futime` |
42| `--status_col` | No | Event status column, default `fustat` |
43| `--risk_col` | No | Risk group column, default `risk_group` |
44| `--time_unit` | No | Time unit label: `year`, `month`, or `day`, default `year` |
45| `--auto_convert_days` | No | Heuristically convert large time values from days when `time_unit` is `year` or `month`, default `true` |
46| `--statistics_method` | No | `logrank` or `wald`, default `logrank` |
47
48## Plot Customization Arguments
49
50| Argument | Default | Description |
51|----------|---------|-------------|
52| `--figure_width` | `10` | Figure width in inches |
53| `--figure_height` | `7` | Figure height in inches |
54| `--figure_family` | `sans` | Font family |
55| `--title_x` | `Time` | X-axis title. If left as default, the script renders `Time (<time_unit>)` |
56| `--title_y` | `Survival probability` | Y-axis title |
57| `--title_main` | empty | Plot title |
58| `--legend_position` | `top` | `top`, `bottom`, `left`, `right`, `none` |
59| `--legend_show` | `true` | Whether to show legend |
60| `--legend_title` | empty | Legend title |
61| `--line_type` | `solid` | Survival line type: `solid`, `dashed`, `dotted`, `dotdash`, `longdash`, `twodash` |
62| `--line_size` | `1` | Survival line width |
63| `--line_colors` | `#4DBBD5,#E64B35,#00A087,#3C5488,#F39B7F,#8491B4,#91D1C2,#DC0000` | Comma-separated group colors |
64| `--censor_show` | `true` | Whether to show censor markers |
65| `--censor_size` | `7` | Censor marker size |
66| `--confidence_show` | `true` | Whether to show confidence interval |
67| `--confidence_alpha` | `0.2` | Confidence band transparency |
68| `--risk_table_show` | `true` | Whether to show the risk table |
69| `--risk_table_border` | `true` | Whether to show the risk table border |
70| `--risk_table_panel` | `false` | Whether to show the risk table panel background |
71| `--risk_table_size` | `6` | Risk table font size |
72| `--axis_title_size` | `12` | Axis title font size |
73| `--axis_text_size` | `10` | Axis tick-label font size |
74| `--legend_text_size` | `11` | Legend text font size |
75
76## Input Requirements
77
78- The input file must contain the requested time, status, and group columns.
79- `.txt` inputs must be tab-delimited.
80- `time` must contain finite non-negative numeric values.
81- `status` must be coded as `0` for censored and `1` for event.
82- The risk group column must be a precomputed categorical grouping variable, not a continuous score column.
83- The risk group column must contain at least 2 groups after filtering.
84- `--line_colors` must provide at least one color per retained group when you override the default palette.
85- Rows with missing time, status, or group values are removed before analysis.
86- At least 2 complete observations must remain after filtering.
87- Near-unique or continuous-looking grouping columns are rejected before model fitting.
88- If `--auto_convert_days true` and `max(time) > 365`, the script assumes the retained time values are in days and converts them to the requested `--time_unit` when `time_unit` is `year` or `month`.
89- Only use `--auto_convert_days true` when the source time column is known to be in days.
90- If your source data are already in years or months, disable `--auto_convert_days` to avoid incorrect conversion.
91- `--statistics_method wald` only supports exactly 2 retained groups; use `logrank` for multi-group comparisons.
92- Invalid plotting parameters such as unsupported `--line_type` values are rejected before plotting.
93
94Example input:
95
96```text
97id fustat futime risk_score risk_group GPR161 RIBC2
98TCGA-C5-A1M5 1 5.62191780821918 -1.10702407761445 low 2.82521576230566 5.35318564979635
99TCGA-VS-A94W 0 3.40547945205479 -0.671246677921865 high 4.26241812321536 4.00802068790173
100```
101
102Bundled test datasets:
103
104- `tests/data/km_sample1.txt`: baseline KM example with `risk_group`
105- `tests/data/km_sample2.txt`: alternate cohort for plotting and statistics examples
106- `tests/data/km_sample3.txt`: additional cohort for validation and repeated testing
107
108## Minimal Workflow
109
1101. Confirm the input file exists and identify the time, status, and group columns.
1112. Run `scripts/main.R` with the requested output directory and any optional plot parameters.
1123. Check the output directory for `km-plot.pdf`.
113
114If you omit `--input_file`, the script exits with `SKILL_MISSING_INPUT`.
115
116## Outputs
117
118Expected output:
119
120```text
121<output_dir>/
122├── km-plot.pdf
123└── session_info.txt
124```
125
126## Interpretation Guide
127
128- Use the survival figure to inspect separation between groups over time.
129- Use the p-value annotation, confidence interval, and risk table in the figure to interpret group separation.
130
131## Time Conversion Caution
132
133- Automatic conversion is a convenience heuristic, not a unit detector.
134- The script only checks whether `max(time) > 365`; it does not infer the true source unit from metadata.
135- If the input time column is already expressed in years or months, run with `--auto_convert_days false`.
136- Review the console log for the conversion warning whenever `time_unit` is `year` or `month`.
137
138## Reproducibility Note
139
140- Repeated runs on identical input should be analytically consistent.
141- The exported `km-plot.pdf` may not be byte-identical across repeated runs because PDF metadata and graphics-device output can vary.
142- If you need byte-stable artifacts, add a deterministic PDF post-processing step outside this skill.
143
144## Do Not Use This Skill When
145
146- You need this tool to derive a cutoff or split a continuous score into risk groups.
147- You need multivariable Cox regression, covariate adjustment, or hazard-ratio modeling beyond the p-value route already exposed here.
148- You need a broader survival-analysis workflow with upstream feature engineering, biomarker selection, or data harmonization.
149- You need multiple plots, report generation, or downstream interpretation beyond producing one Kaplan-Meier figure and session metadata.
150
151## Read These Files When Needed
152
153| Need | File |
154|------|------|
155| Kaplan-Meier method details and interpretation | `references/algorithm.md` |
156| More CLI examples | `references/cli-guide.md` |
157| Error diagnosis | `references/troubleshooting.md` |
158| Main execution entry point | `scripts/main.R` |
159| Sample test data | `tests/data/km_sample1.txt`, `tests/data/km_sample2.txt`, `tests/data/km_sample3.txt` |
160
161## Quick Examples
162
163Basic Kaplan-Meier analysis:
164
165```bash
166Rscript scripts/main.R \
167 --input_file tests/data/km_sample1.txt \
168 --output_dir tests/output_basic
169```
170
171Custom column names:
172
173```bash
174Rscript scripts/main.R \
175 --input_file tests/data/km_sample1.txt \
176 --time_col futime \
177 --status_col fustat \
178 --risk_col risk_group \
179 --output_dir tests/output_custom_columns
180```
181
182Custom plot title:
183
184```bash
185Rscript scripts/main.R \
186 --input_file tests/data/km_sample2.txt \
187 --title_main "Study KM Curve" \
188 --output_dir tests/output_title
189```
190
191Hide confidence interval and risk table:
192
193```bash
194Rscript scripts/main.R \
195 --input_file tests/data/km_sample3.txt \
196 --confidence_show false \
197 --risk_table_show false \
198 --output_dir tests/output_simple
199```
200
201## Validation
202
203```bash
204Rscript scripts/main.R --help
205```
206
207```bash
208Rscript scripts/main.R \
209 --input_file tests/data/km_sample1.txt \
210 --output_dir tests/validation_output
211```
212
213After running analysis, verify that `tests/validation_output/km-plot.pdf` exists.
214
215## Common Errors
216
217- `SKILL_FILE_NOT_FOUND`: Input file path is wrong or inaccessible.
218- `SKILL_MISSING_COLUMNS`: A requested time, status, or risk group column is missing.
219- `SKILL_INVALID_DATA`: Input data is malformed or unsuitable for survival analysis.
220- `SKILL_INVALID_DATA`: A continuous or near-unique risk column was supplied where a categorical group column is required.
221- `SKILL_INVALID_PARAMETER`: An argument value is invalid.
222- `SKILL_INVALID_PARAMETER`: Plotting options such as `--line_type` or `--line_colors` are incompatible with the retained groups.
223- `SKILL_INSUFFICIENT_DATA`: Too few complete observations remain after filtering.
224- `SKILL_DEPENDENCY_MISSING`: A required R package such as `optparse` or `survival` is unavailable.
225
226If the issue is not obvious, read `references/troubleshooting.md`.