AE summary¶
This example shows how to create a simplified adverse events summary table.
Imports¶
Create data for RTF table¶
Load adverse events data from parquet file:
Process the data to create summary statistics:
# First, get the total number of subjects per treatment group
subjects_per_trt = df.group_by("TRTA").agg(pl.col("USUBJID").n_unique().alias("n_subj"))
# Count subjects with each AE by treatment group and calculate percentages
ae_t1 = (
df.group_by(["TRTA", "AEDECOD"])
.agg(pl.col("USUBJID").n_unique().alias("n_ae"))
.join(subjects_per_trt, on="TRTA")
.with_columns((pl.col("n_ae") / pl.col("n_subj") * 100).round(2).alias("pct"))
# Only show AE terms with at least 5 subjects in one treatment group
.filter(pl.col("n_ae") > 5)
)
# Pivot the data to create wide format with n and pct for each treatment
# First, melt the n_ae and pct columns
ae_long = ae_t1.select(["TRTA", "AEDECOD", "n_ae", "pct"]).unpivot(
index=["TRTA", "AEDECOD"],
on=["n_ae", "pct"],
variable_name="var",
value_name="value",
)
# Create combined column names for pivoting
ae_long = ae_long.with_columns((pl.col("TRTA") + "_" + pl.col("var")).alias("temp"))
# Pivot to wide format
ae_wide = ae_long.pivot(values="value", index="AEDECOD", on="temp").fill_null(0)
# Ensure columns are in the correct order
col_order = [
"AEDECOD",
"Placebo_n_ae",
"Placebo_pct",
"Xanomeline High Dose_n_ae",
"Xanomeline High Dose_pct",
"Xanomeline Low Dose_n_ae",
"Xanomeline Low Dose_pct",
]
ae_t1_final = (
ae_wide.select(col_order)
.with_columns(pl.col(pl.Float64).cast(pl.String))
.sort("AEDECOD")
)
print(ae_t1_final.head(10))
shape: (10, 7)
┌──────────────┬─────────────┬─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
│ AEDECOD ┆ Placebo_n_a ┆ Placebo_pct ┆ Xanomeline ┆ Xanomeline ┆ Xanomeline ┆ Xanomeline │
│ --- ┆ e ┆ --- ┆ High ┆ High ┆ Low ┆ Low │
│ str ┆ --- ┆ str ┆ Dose_n_ae ┆ Dose_pct ┆ Dose_n_ae ┆ Dose_pct │
│ ┆ str ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ ┆ ┆ ┆ str ┆ str ┆ str ┆ str │
╞══════════════╪═════════════╪═════════════╪═════════════╪═════════════╪═════════════╪═════════════╡
│ APPLICATION ┆ 0.0 ┆ 0.0 ┆ 7.0 ┆ 8.86 ┆ 9.0 ┆ 11.69 │
│ SITE ┆ ┆ ┆ ┆ ┆ ┆ │
│ DERMATITIS ┆ ┆ ┆ ┆ ┆ ┆ │
│ APPLICATION ┆ 0.0 ┆ 0.0 ┆ 15.0 ┆ 18.99 ┆ 12.0 ┆ 15.58 │
│ SITE ┆ ┆ ┆ ┆ ┆ ┆ │
│ ERYTHEMA ┆ ┆ ┆ ┆ ┆ ┆ │
│ APPLICATION ┆ 0.0 ┆ 0.0 ┆ 9.0 ┆ 11.39 ┆ 9.0 ┆ 11.69 │
│ SITE ┆ ┆ ┆ ┆ ┆ ┆ │
│ IRRITATION ┆ ┆ ┆ ┆ ┆ ┆ │
│ APPLICATION ┆ 6.0 ┆ 8.7 ┆ 22.0 ┆ 27.85 ┆ 22.0 ┆ 28.57 │
│ SITE ┆ ┆ ┆ ┆ ┆ ┆ │
│ PRURITUS ┆ ┆ ┆ ┆ ┆ ┆ │
│ APPLICATION ┆ 0.0 ┆ 0.0 ┆ 6.0 ┆ 7.59 ┆ 0.0 ┆ 0.0 │
│ SITE ┆ ┆ ┆ ┆ ┆ ┆ │
│ VESICLES ┆ ┆ ┆ ┆ ┆ ┆ │
│ COUGH ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 6.0 ┆ 7.79 │
│ DIARRHOEA ┆ 9.0 ┆ 13.04 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ DIZZINESS ┆ 0.0 ┆ 0.0 ┆ 12.0 ┆ 15.19 ┆ 8.0 ┆ 10.39 │
│ ERYTHEMA ┆ 9.0 ┆ 13.04 ┆ 14.0 ┆ 17.72 ┆ 15.0 ┆ 19.48 │
│ HEADACHE ┆ 7.0 ┆ 10.14 ┆ 6.0 ┆ 7.59 ┆ 0.0 ┆ 0.0 │
└──────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
Define table format¶
Prepare the data for RTF output:
# Define column headers
header1 = [" ", "Placebo", "Drug High Dose", "Drug Low Dose"]
header2 = [" ", "n", "(%)", "n", "(%)", "n", "(%)"]
# Create RTF components
col_header1 = rtf.RTFColumnHeader(
text=header1, col_rel_width=[4, 2, 2, 2], text_justification=["l", "c", "c", "c"]
)
col_header2 = rtf.RTFColumnHeader(
text=header2,
col_rel_width=[4] + [1] * 6,
text_justification=["l", "c", "c", "c", "c", "c", "c"],
border_top=[""] + ["single"] * 6,
border_left=["single"] + ["single", ""] * 3,
)
# Create table body
tbl_body = rtf.RTFBody(
col_rel_width=[4] + [1] * 6,
text_justification=["l"] + ["c"] * 6,
border_left=["single"] + ["single", ""] * 3,
)
Create the RTF document with formatting:
# Create RTF document
doc = rtf.RTFDocument(
df=ae_t1_final,
rtf_title=rtf.RTFTitle(
text=[
"Analysis of Subjects With Specific Adverse Events",
"(Incidence > 5 Subjects in One or More Treatment Groups)",
"ASaT",
]
),
rtf_column_header=[col_header1, col_header2],
rtf_body=tbl_body,
rtf_footnote=rtf.RTFFootnote(
text=["{^\\dagger}This is footnote 1", "This is footnote 2"],
text_convert=[[True]], # Enable LaTeX symbol conversion
),
rtf_source=rtf.RTFSource(text=["Source: xxx"]),
)
# Output .rtf file
doc.write_rtf("example-ae-summary.rtf")