Data sources and formats

Real survival data arrives in many shapes. It might be a Pandas data frame you built from a CSV, a Polars data frame from a Parquet file, a table pulled straight from a database, or one of the datasets bundled with Greenwood for learning and testing. One of the design goals of this package is that none of this should matter: you bring the data in whatever form you already have, and Greenwood works with it directly. This page explains how, and lists the datasets that ship with the package.

Backend-agnostic by design

Greenwood does not have its own data frame type and does not force you to convert your data into one. Instead it is built on Narwhals, a lightweight compatibility layer that lets a library speak to many data frame backends through one interface. When you hand Greenwood a data frame or a column, it reads the values through Narwhals and runs its numerical work on the underlying arrays. Your original object is never mutated and never copied into a foreign format.

In practice this means you can pass data from any of the backends Narwhals supports. Three of these are covered directly by the Greenwood test suite, which checks that they all produce identical estimates on the same data.

  • Pandas, the most widely used data frame library, and the default for the bundled datasets
  • Polars, a fast, multi-threaded, Arrow-based data frame library, well suited to large datasets
  • PyArrow tables, the in-memory Arrow format that many file readers and databases produce

Other backends that Narwhals supports, such as Modin, cuDF, and DuckDB, use the same interface and are expected to work the same way, though the test suite pins parity on the three above.

NoteWhat “backend-agnostic” buys you

You do not have to rewrite your analysis when you switch data frame libraries. Code written for a Pandas workflow runs unchanged when the data arrives as Polars, because Greenwood reads both through the same interface. This also means results do not depend on the backend: the same data produces the same estimates regardless of where the frame came from. The test suite verifies this for Pandas, Polars, and PyArrow on identical inputs.

Passing columns and passing frames

There are two ways to feed data to Greenwood, and both are always available.

The first is to pass individual columns to a Surv constructor. This is how you build the response. A column can be a Pandas Series, a Polars Series, a NumPy array, or an ordinary Python list. Greenwood treats them all the same.

import greenwood as gw

# Load the bundled lung dataset as a Polars DataFrame
lung = gw.load_dataset("lung", backend="polars")

# Build a right-censored response; status == 2 marks a death
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))

# Display the response summary
y
Surv(type=right, n=228, events=165)

The second is to pass a whole data frame of covariates to a model. The model reads the columns it needs, converts non-numeric columns to indicator variables, and drops rows with missing values, just as R’s modeling functions do. We fit the model in its own cell, then set it aside and look at its results through the tidy functions below.

# Fit a Cox model with age, sex, and ECOG score as covariates
cox = gw.CoxPH().fit(y, lung[["age", "sex", "ph.ecog"]])

# Print the coefficient table and global test statistics
cox
CoxPH (Cox proportional hazards model, ties='efron')

            coef  exp(coef)  se(coef)       z          p
age      0.01107      1.011  0.009267   1.194     0.2324
sex      -0.5526     0.5754    0.1677  -3.294  0.0009861
ph.ecog   0.4637       1.59    0.1136   4.083  4.447e-05

n = 227, events = 164
Likelihood ratio test = 30.5 on 3 df, p = 1.083e-06

Printing a fitted model shows a readable summary, but for programmatic use you read its results through tidy output frames. The tidy function returns one row per model term, and passing exponentiate=True reports hazard ratios rather than raw coefficients.

# Extract a tidy per-term table; exponentiate=True gives hazard ratios
gw.tidy(cox, exponentiate=True, format="polars")
PolarsRows3Columns7
term
str
estimate
f64
std_error
f64
statistic
f64
p_value
f64
conf_low
f64
conf_high
f64
0 age 1.01112822772 0.0092674110137 1.19415924725 0.232415681 0.99292809717 1.02966196224
1 sex 0.57544455619 0.167739053787 -3.29447664826 0.000986051372138 0.414213018549 0.799435127387
2 ph.ecog 1.58999119005 0.113577266162 4.0829339448 4.44706665186e-05 1.27267517777 1.98642358129

These two patterns (columns into Surv, frames into models) are the only interface you need for the entire package. Every page in this guide uses one or both of them.

Choosing a backend

The load_dataset() function is itself dataframe-agnostic. With its default it returns a Polars data frame when Polars is installed, falls back to Pandas when only Pandas is available, and raises a clear error if neither is. When you want a specific type, name it with the backend= argument.

# Load the same dataset explicitly in each backend
lung_pd = gw.load_dataset("lung", backend="pandas")
lung_pl = gw.load_dataset("lung", backend="polars")

# Confirm each object belongs to a different library
type(lung_pd).__module__.split(".")[0], type(lung_pl).__module__.split(".")[0]
('pandas', 'polars')

The backend makes no difference to any result. The same model fit on the Pandas frame and on the Polars frame returns the same coefficients, a property the test suite checks on every release. To show this, we first build a response from the Polars columns. The resulting Surv object looks the same as one built from Pandas: it records the same times and events, because Greenwood read both through Narwhals.

# Build a response from the Polars columns — identical to building from Pandas
y_pl = gw.Surv.right(lung_pl["time"], event=(lung_pl["status"] == 2))

# Display the summary; it looks the same regardless of backend
y_pl
Surv(type=right, n=228, events=165)

Fitting a Cox model on the Polars-backed response and covariates, then viewing the result with to_frame(), gives the same coefficient table you would get from the Polars DataFrame.

# Fit on the Polars frame and export the coefficient table — same numbers as Pandas
gw.CoxPH().fit(y_pl, lung_pl[["age", "sex"]]).to_frame(format="polars")
PolarsRows2Columns7
term
str
estimate
f64
std_error
f64
statistic
f64
p_value
f64
conf_low
f64
conf_high
f64
0 age 0.0170453318454 0.00922327347697 1.8480783301 0.0645910121295 -0.00103195198901 0.0351226156798
1 sex -0.513218517108 0.167457962356 -3.06476031291 0.00217844504671 -0.84143009225 -0.185006941967

You can choose whichever backend fits your existing workflow. If your pipeline already uses Polars, stick with Polars. If it uses Pandas, stick with Pandas. The choice has no effect on any numerical result.

TipReading from files and databases

Greenwood does not read files itself, and it does not need to. Use your DataFrame library’s reader (pandas.read_csv(), polars.read_parquet(), a database query, and so on) to get a DataFrame, then pass its columns to Surv exactly as above. Anything that produces a supported DataFrame is a valid source.

Shaping raw study data for Surv

Loading a data frame is rarely the last step before building a response. Real study exports often arrive in a form that needs light transformation before the times and event indicators are ready for Surv. Three situations come up often: (1) the data stores calendar dates rather than durations, (2) the event indicator is encoded in a compound or string status column, and (3) a multi-endpoint DataFrame mixes rows that belong to different analyses.

Computing durations from timestamps

The most common transformation is computing the elapsed time between two date columns. Subtract the enrollment date from the exit date and convert the result to your preferred time unit. Polars returns a Duration type from date subtraction; .dt.total_days() gives integer days, which you then cast to float for Surv.

import polars as pl

# Build a simulated study export with enrollment dates, exit dates, and outcomes
study = pl.DataFrame({
    "subject": [1, 2, 3, 4, 5, 6],
    "enroll":  ["2021-03-01", "2021-03-15", "2021-04-01",
                "2021-04-20", "2021-05-01", "2021-06-01"],
    "exit":    ["2022-01-10", "2021-09-22", "2023-01-01",
                "2021-12-05", "2022-08-14", "2022-03-30"],
    "outcome": ["died", "censored", "censored", "died", "withdrew", "died"],
}).with_columns(
    pl.col("enroll", "exit").cast(pl.Date)
).with_columns(
    # Subtract dates to get a Duration, then convert to float days
    time=(pl.col("exit") - pl.col("enroll")).dt.total_days().cast(pl.Float64),
    # True only for "died"; censored and withdrew both become censored observations
    event=(pl.col("outcome") == "died"),
)

# Build the right-censored response from the computed columns
y = gw.Surv.right(study["time"], event=study["event"])

# Display the response summary
y
Surv(type=right, n=6, events=3)

A few things to notice in this example. First, the outcome column uses three values: "died" (the event), "censored" (lost to follow-up at the exit date), and "withdrew" (left the study early). All three map cleanly to a boolean event indicator: the event is True only for "died", and all other outcomes become censored observations. Second, the exit date serves the same role regardless of the reason for exit: it is always the last time at which the subject was observed, and the event indicator records what happened at that time.

NoteMissing values

Surv raises an error if time or event contains null values. Drop or impute missing rows before constructing the response:

study_clean = study.drop_nulls(subset=["time", "event"])

Encoding from compound status columns

Some datasets store multiple outcome levels in a single integer status column. pbc is a typical example: status is 0 (censored), 1 (transplant), or 2 (dead). The right encoding depends on the analysis you intend to run.

# Load the pbc dataset; its status column has three levels (0, 1, 2)
pbc = gw.load_dataset("pbc", backend="polars")

# All-cause analysis: transplant and death are both events
y_all = gw.Surv.right(pbc["time"], event=(pbc["status"] > 0))

# Death-only: transplant becomes censoring (patient still alive at last contact)
y_death = gw.Surv.right(pbc["time"], event=(pbc["status"] == 2))

# Compare event counts between the two endpoint definitions
print("all-cause: ", y_all)
print("death-only:", y_death)
all-cause:  Surv(type=right, n=418, events=186)
death-only: Surv(type=right, n=418, events=161)

The event counts differ because 25 subjects reached transplant rather than death: the all-cause endpoint treats them as events, the death-only endpoint treats them as censored. Which is correct depends entirely on your research question. For a competing-risks analysis that keeps the two outcomes separate, pass the full status column to AalenJohansen or FineGray with explicit event codes. See the competing-risks chapter for that pattern.

Filtering multi-endpoint frames

Some study exports give each subject one row per potential endpoint. The colon dataset is structured this way: etype is 1 for recurrence and 2 for death, so the full frame has 1,858 rows for 929 patients. Mixing rows from different endpoints in a single Surv is meaningless, so always filter to one endpoint first.

# Load the colon dataset; each patient contributes two rows, one per endpoint
colon = gw.load_dataset("colon", backend="polars")

# Keep only the recurrence-endpoint rows
recurrence = colon.filter(pl.col("etype") == 1)

# Build the response from the filtered frame (929 patients, not 1858 rows)
y_recur = gw.Surv.right(recurrence["time"], event=recurrence["status"])

# Display the response summary
y_recur
Surv(type=right, n=929, events=468)

The same principle applies to mgus2, which stores its two competing endpoints in separate column pairs (ptime/pstat for progression, futime/death for death) rather than separate rows. There you select the column pair that matches the endpoint you want, or pass both to a competing-risks model.

Tidy output frames

Every estimator and model returns its results as tidy data frames, through the to_frame() method and through the tidy() and glance() functions. Pass format= ("pandas", "polars", or "pyarrow") to choose the backend; when you leave it off, Greenwood auto-detects one (Polars if installed, otherwise Pandas, otherwise PyArrow). This makes the results easy to inspect, filter, join, or pass on to a plotting or table library.

# Load data and build the response
lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))

# Fit a Cox model with three covariates
cox = gw.CoxPH().fit(y, lung[["age", "sex", "ph.ecog"]])

# Retrieve the one-row model summary: n, events, log-likelihood, AIC
gw.glance(cox, format="polars")
PolarsRows1Columns10
n
i64
nevent
i64
loglik
f64
aic
f64
lr_statistic
f64
df
i64
lr_p_value
f64
frailty_theta
null
frailty_lrt_statistic
null
frailty_lrt_p_value
null
0 227 164 -729.230121375 1464.46024275 30.5006687732 3 1.0828176992e-06 None None None

The tidy and glance functions follow the same conventions as R’s broom package, so a fitted model always yields a per-term table (tidy()) and a one-row model summary (glance()). This is the part that lets Greenwood feed publication tables in Great Tables.

Datasets bundled with Greenwood

For learning, testing, and reproducible examples, Greenwood ships six classic survival datasets drawn from R’s survival package. You can load any of them by name with the load_dataset() function, and you can list them with available_datasets().

# List the names of all datasets bundled with Greenwood
gw.available_datasets()
['colon', 'lung', 'mgus2', 'ovarian', 'pbc', 'pbcseq', 'veteran']

The six datasets vary widely in size, covariate richness, and event structure. The sections below describe each one, identify which Greenwood models are a natural fit, and display the raw data in an interactive explorer so you can inspect columns and spot missing values before writing a single line of analysis code.

lung: NCCTG lung cancer

The lung dataset follows 228 patients enrolled in a North Central Cancer Treatment Group trial of advanced lung cancer. It is the most commonly-used type of example throughout the Greenwood documentation and the most commonly cited benchmark in the Python and R survival-analysis literature.

Columns: inst (institution code), time (survival days), status (1 = censored, 2 = dead), age, sex (1 = male, 2 = female), ph.ecog (ECOG performance score 0–4), ph.karno (Karnofsky score rated by physician), pat.karno (Karnofsky score rated by patient), meal.cal (calories consumed at meals), wt.loss (weight loss in the last six months).

Model fit: The modest size, clean right-censoring, and mix of continuous and ordinal covariates make lung suitable for virtually every model in Greenwood. Use it for Kaplan-Meier and Nelson-Aalen curves (overall or stratified by sex or ph.ecog), log-rank and related group-comparison tests, Cox proportional-hazards regression, the Royston-Parmar flexible parametric model, and AFT regression. It is the standard dataset used in the Surv construction examples throughout this guide.

NoteEvent coding

status uses the R-style 1/2 convention: 1 = censored, 2 = dead. Build the response as Surv.right(time, event=(status == 2)).

PolarsRows228Columns10
lung: 228 patients, 10 variables
inst
i64
time
i64
status
i64
age
i64
sex
i64
ph.ecog
i64
ph.karno
i64
pat.karno
i64
meal.cal
i64
wt.loss
i64
0 3 306 2 74 1 1 90 100 1175 None
1 3 455 2 68 1 0 90 90 1225 15
2 3 1010 1 56 1 0 90 90 None 15
3 5 210 2 57 1 1 90 60 1150 11
4 1 883 2 60 1 0 100 90 None 0
5 12 1022 1 74 1 1 50 80 513 0
6 7 310 2 68 2 2 70 60 384 10
7 11 361 2 71 2 2 60 80 538 1
8 1 218 2 53 1 1 70 80 825 16
9 7 166 2 61 1 2 70 70 271 34

veteran: Veterans’ Administration lung cancer trial

veteran is a randomized clinical trial comparing two treatments in 137 male veterans with inoperable lung cancer. Its standout feature is the celltype column, which partitions patients into four histological groups (squamous, small cell, adeno, and large cell). This makes it the natural choice for demonstrating stratified Kaplan-Meier curves and multi-group comparison tests.

Columns: trt (1 = standard, 2 = test), celltype ("squamous"/"smallcell"/"adeno"/ "large"), time (survival days), status (0 = censored, 1 = dead), karno (Karnofsky performance score), diagtime (months from diagnosis to study entry), age, prior (prior therapy: 0 or 10).

Model fit: veteran is ideal for Kaplan-Meier curves stratified by trt or celltype, log-rank tests, pairwise log-rank, and trend tests. For regression, CoxPH accepts the celltype string column directly and converts it to treatment-coded dummies automatically, giving one hazard ratio per cell type relative to the reference level.

PolarsRows137Columns8
veteran: 137 patients, 8 variables
trt
i64
celltype
str
time
i64
status
i64
karno
i64
diagtime
i64
age
i64
prior
i64
0 1 squamous 72 1 60 7 69 0
1 1 squamous 411 1 70 5 64 10
2 1 squamous 228 1 60 3 38 0
3 1 squamous 126 1 60 9 63 10
4 1 squamous 118 1 70 11 65 10
5 1 squamous 10 1 20 5 49 0
6 1 squamous 82 1 40 10 69 10
7 1 squamous 110 1 80 29 68 0
8 1 squamous 314 1 50 18 43 0
9 1 squamous 100 0 70 6 70 0

ovarian: Ovarian cancer survival

ovarian is a deliberately small dataset (26 patients) from a trial comparing two chemotherapy regimens for ovarian cancer. Its small size makes it ideal for teaching, for verifying that a method produces the right result on data you can inspect by eye, and for quick checks during development.

Columns: futime (follow-up days), fustat (0 = censored, 1 = dead), age, resid.ds (residual disease after surgery: 1 = no, 2 = yes), rx (treatment group: 1 or 2), ecog.ps (ECOG performance status).

Model fit: Because of its size, ovarian is best used with non-parametric estimators (KaplanMeier, NelsonAalen) and simple group comparisons (logrank_test()). Regression models can be fit but coefficient estimates will have wide confidence intervals. Use pbc or colon when you need a richer covariate structure.

PolarsRows26Columns6
ovarian: 26 patients, 6 variables
futime
i64
fustat
i64
age
f64
resid.ds
i64
rx
i64
ecog.ps
i64
0 59 1 72.3315 2 1 1
1 115 1 74.4932 2 1 1
2 156 1 66.4658 2 1 2
3 421 0 53.3644 2 2 1
4 431 1 50.3397 2 1 1
5 448 0 56.4301 1 1 2
6 464 1 56.937 2 2 2
7 475 1 59.8548 2 2 2
8 477 0 64.1753 2 1 1
9 563 1 55.1781 1 2 2

pbc: Mayo Clinic primary biliary cholangitis

pbc records 418 patients enrolled in a Mayo Clinic randomized trial of D-penicillamine for primary biliary cholangitis, a chronic liver disease. With 20 columns including laboratory values, clinical signs, and histological staging, it is the reference dataset for high-dimensional regression in Greenwood.

Columns: id, time (days to death or transplant), status (0 = censored, 1 = transplant, 2 = dead), trt (1 = D-penicillamine, 2 = placebo), age, sex, ascites, hepato (hepatomegaly), spiders, edema, bili (serum bilirubin), chol (cholesterol), albumin, copper, alk.phos (alkaline phosphatase), ast, trig (triglycerides), platelet, protime (prothrombin time), stage (histologic stage 14).

Model fit: pbc is the standard choice for CoxPH with many covariates and for CoxNet (penalized Cox) when you want automatic variable selection or regularization. The Royston-Parmar flexible parametric model also fits well here. Because status has three levels, you can treat transplant and death as a combined endpoint (event=(status > 0)) for a standard right-censored analysis, or separate them into competing events for AalenJohansen and FineGray.

NoteEvent coding

status has three levels: 0 = censored, 1 = transplant, 2 = dead. For an all-cause analysis use event=(status > 0). For competing risks, pass the full column with explicit event codes to AalenJohansen or FineGray.

PolarsRows418Columns20
pbc: 418 patients, 20 variables
id
i64
time
i64
status
i64
trt
i64
age
f64
sex
str
ascites
i64
hepato
i64
spiders
i64
edema
f64
bili
f64
chol
i64
albumin
f64
copper
i64
alk.phos
f64
ast
f64
trig
i64
platelet
i64
protime
f64
stage
i64
0 1 400 2 1 58.765229295 f 1 1 1 1 14.5 261 2.6 156 1718 137.95 172 190 12.2 4
1 2 4500 0 1 56.4462696783 f 0 1 1 0 1.1 302 4.14 54 7394.8 113.52 88 221 10.6 3
2 3 1012 2 1 70.0725530459 m 0 0 0 0.5 1.4 176 3.48 210 516 96.1 55 151 12 4
3 4 1925 2 1 54.7405886379 f 0 1 1 0.5 1.8 244 2.54 64 6121.8 60.63 92 183 10.3 4
4 5 1504 1 2 38.1054072553 f 0 1 1 0 3.4 279 3.53 143 671 113.15 72 136 10.9 3
5 6 2503 2 2 66.2587268994 f 0 1 0 0 0.8 248 3.98 50 944 93 63 None 11 3
6 7 1832 0 2 55.5345653662 f 0 1 0 0 1 322 4.09 52 824 60.45 213 204 9.7 3
7 8 2466 2 2 53.0568104038 f 0 0 0 0 0.3 280 4 52 4651.2 28.38 189 373 11 3
8 9 2400 2 1 42.507871321 f 0 0 1 0 3.2 562 3.08 79 2276 144.15 88 251 11 2
9 10 51 2 2 70.559890486 f 1 0 1 1 12.6 200 2.74 140 918 147.25 143 302 11.5 4

colon: Adjuvant therapy for colon cancer

colon is Greenwood’s largest dataset at 1858 rows. It comes from a three-arm trial (observation, levamisole, and levamisole plus 5-FU) for adjuvant therapy after surgery for colon cancer. The key structural feature is the etype column: each patient contributes two rows, one for recurrence (etype = 1) and one for death (etype = 2), so the full frame contains roughly twice the number of subjects.

Columns: id, study, rx (Obs / Lev / Lev+5FU), sex, age, obstruct, perfor (bowel perforation), adhere, nodes (positive lymph nodes), status (0 = censored, 1 = event), differ (tumor differentiation), extent (depth of invasion), surg (short / long time from surgery to registration), node4 (nodes > 4), time, etype (1 = recurrence, 2 = death).

Model fit: Always filter to one endpoint before fitting: df.filter(pl.col("etype") == 1) for recurrence or == 2 for death. The recurrence endpoint is well suited to Kaplan-Meier curves and log-rank tests comparing the three treatment arms; the large sample gives precise estimates. Filtering to etype == 2 and treating the recurrence event as a competing risk gives a natural setup for AalenJohansen and FineGray.

PolarsRows1,858Columns16
colon: 1858 rows (2 endpoints per patient), 16 variables
id
i64
study
i64
rx
str
sex
i64
age
i64
obstruct
i64
perfor
i64
adhere
i64
nodes
i64
status
i64
differ
i64
extent
i64
surg
i64
node4
i64
time
i64
etype
i64
0 1 1 Lev+5FU 1 43 0 0 0 5 1 2 3 0 1 1521 2
1 1 1 Lev+5FU 1 43 0 0 0 5 1 2 3 0 1 968 1
2 2 1 Lev+5FU 1 63 0 0 0 1 0 2 3 0 0 3087 2
3 2 1 Lev+5FU 1 63 0 0 0 1 0 2 3 0 0 3087 1
4 3 1 Obs 0 71 0 0 1 7 1 2 2 0 1 963 2
5 3 1 Obs 0 71 0 0 1 7 1 2 2 0 1 542 1
6 4 1 Lev+5FU 0 66 1 0 0 6 1 2 3 1 1 293 2
7 4 1 Lev+5FU 0 66 1 0 0 6 1 2 3 1 1 245 1
8 5 1 Obs 1 69 0 0 0 22 1 2 3 1 1 659 2
9 5 1 Obs 1 69 0 0 0 22 1 2 3 1 1 523 1

mgus2: Monoclonal gammopathy

mgus2 is Greenwood’s canonical competing-risks dataset. It follows 1,384 patients diagnosed with monoclonal gammopathy of undetermined significance (MGUS), a precursor plasma-cell condition, tracking two competing endpoints: progression to plasma-cell malignancy (pstat, time in ptime) and death without progression (death, time in futime). Because a patient who progresses cannot later die as a non-progressor, the two events compete; a Kaplan-Meier analysis would overestimate the probability of each event, so this dataset is the motivating example for cumulative incidence functions in this guide.

Columns: id, age, sex, dxyr (year of diagnosis), hgb (hemoglobin), creat (creatinine), mspike (M-spike size in g/dL), ptime (months to progression), pstat (0 = no progression, 1 = progressed), futime (months to death or censoring), death (0 = alive, 1 = dead).

Model fit: mgus2 is designed for competing-risks analysis. Use AalenJohansen for non-parametric cumulative incidence functions and FineGray for regression on the cause-specific subdistribution hazard. The MultiState model can extend the analysis to a three-state illness-death structure (MGUS -> progression -> death). The competing-risks page of this guide builds its examples entirely on this dataset.

PolarsRows1,384Columns11
mgus2: 1384 patients, 11 variables
id
i64
age
i64
sex
str
dxyr
i64
hgb
f64
creat
f64
mspike
f64
ptime
i64
pstat
i64
futime
i64
death
i64
0 1 88 F 1981 13.1 1.3 0.5 30 0 30 1
1 2 78 F 1968 11.5 1.2 2 25 0 25 1
2 3 94 M 1980 10.5 1.5 2.6 46 0 46 1
3 4 68 M 1977 15.2 1.2 1.2 92 0 92 1
4 5 90 F 1973 10.7 0.8 1 8 0 8 1
5 6 90 M 1990 12.9 1 0.5 4 0 4 1
6 7 89 F 1974 10.5 0.9 1.3 151 0 151 1
7 8 87 F 1974 12.3 1.2 1.6 2 0 2 1
8 9 86 F 1994 14.5 0.9 2.4 57 0 57 0
9 10 79 F 1981 9.4 1.1 2.3 136 0 136 1
WarningEvent coding in the bundled data

Several of these datasets follow R’s convention rather than the 0/1 convention for the status column. lung codes status as 1 = censored and 2 = dead. pbc uses three levels (0/1/2). Always inspect the column and convert it explicitly when building the response. See Survival data for why Greenwood does not guess at event coding.

Next steps

You can now bring survival data into Greenwood from whatever source you have, and you know what the bundled datasets contain.