Treatment Response Analysis in Oncology
Source:vignettes/legacy/12-treatment-response-analysis-legacy.Rmd
12-treatment-response-analysis-legacy.Rmd
Introduction
Treatment response analysis is crucial in oncology research for evaluating therapeutic efficacy and understanding patient outcomes. This vignette demonstrates specialized functions in ClinicoPathDescriptives for analyzing treatment response data, including waterfall plots, swimmer plots, and RECIST criteria implementation.
Oncology Response Evaluation
RECIST Criteria
Response Evaluation Criteria in Solid Tumors (RECIST) provides standardized guidelines for measuring treatment response:
- Complete Response (CR): Disappearance of all target lesions
- Partial Response (PR): ≥30% decrease in sum of target lesion diameters
- Progressive Disease (PD): ≥20% increase in sum of target lesion diameters
- Stable Disease (SD): Neither PR nor PD criteria met
Dataset Preparation
# Create comprehensive treatment response dataset
response_data <- treatmentResponse %>%
mutate(
# RECIST classification based on percentage change
RECIST_Response = case_when(
is.na(ResponseValue) ~ "Not Evaluable",
ResponseValue <= -30 ~ "Partial Response (PR)",
ResponseValue > -30 & ResponseValue < 20 ~ "Stable Disease (SD)",
ResponseValue >= 20 ~ "Progressive Disease (PD)"
),
# Additional response categories
Response_Category = case_when(
is.na(ResponseValue) ~ "Missing",
ResponseValue < 0 ~ "Tumor Shrinkage",
ResponseValue == 0 ~ "No Change",
ResponseValue > 0 ~ "Tumor Growth"
),
# Best response categories
Best_Response = case_when(
ResponseValue <= -50 ~ "Major Response",
ResponseValue <= -30 ~ "Partial Response",
ResponseValue > -30 & ResponseValue < 20 ~ "Stable Disease",
ResponseValue >= 20 & ResponseValue < 50 ~ "Progressive Disease",
ResponseValue >= 50 ~ "Rapid Progression",
TRUE ~ "Not Evaluable"
),
# Extract patient number for sorting
PatientNum = as.numeric(gsub("PT", "", PatientID))
) %>%
arrange(ResponseValue)
# Summary statistics
cat("Treatment Response Dataset Summary:\n")
cat("Total Patients:", nrow(response_data), "\n")
cat("Evaluable Patients:", sum(!is.na(response_data$ResponseValue)), "\n")
cat("Missing Data:", sum(is.na(response_data$ResponseValue)), "\n\n")
# Response distribution
table(response_data$RECIST_Response)
Basic Response Analysis
Response Distribution
# Analyze response categories
reportcat(
data = response_data,
vars = c("RECIST_Response", "Best_Response", "Response_Category")
)
Waterfall Plot Analysis
The waterfall plot is the gold standard for visualizing individual patient treatment responses in oncology trials.
# Basic waterfall plot
waterfall(
data = response_data,
patientID = "PatientID",
responseVar = "ResponseValue",
timeVar = NULL,
showWaterfallPlot = TRUE
)
Swimmer Plot Analysis
Swimmer plots show individual patient timelines, treatment durations, and clinical events over time.
# Prepare data for swimmer plot by merging with clinical data
# Create synthetic timeline data based on available information
swimmer_data <- histopathology %>%
select(ID, Group, OverallTime, Outcome, Death, TStage, Grade) %>%
mutate(
PatientID = paste0("PT", sprintf("%04d", ID)),
Treatment_Duration = pmax(1, OverallTime * runif(n(), 0.6, 1.0)), # Synthetic treatment duration
Event_Time = ifelse(Outcome == 1, OverallTime, NA),
Response_Time = Treatment_Duration * runif(n(), 0.3, 0.8), # Synthetic response assessment time
Treatment_Status = case_when(
Death == "DOĞRU" ~ "Discontinued - Death",
Outcome == 1 ~ "Discontinued - Progression",
TRUE ~ "Ongoing"
)
) %>%
filter(ID <= 50) %>% # Limit to first 50 patients for clarity
arrange(desc(OverallTime))
# Generate swimmer plot
swimmerplot(
data = swimmer_data,
patientID = "PatientID",
startTime = "Treatment_Duration",
endTime = "OverallTime",
responseVar = NULL,
sortVariable = NULL,
milestone1Date = NULL,
milestone2Date = NULL,
milestone3Date = NULL,
milestone4Date = NULL,
milestone5Date = NULL
)
Response Correlation Analysis
Response by Patient Characteristics
# Merge response data with clinical characteristics
combined_data <- response_data %>%
left_join(
histopathology %>%
select(ID, Group, Age, Sex, Grade, TStage, LVI, PNI, LymphNodeMetastasis) %>%
mutate(PatientID = paste0("PT", sprintf("%04d", ID))),
by = "PatientID"
) %>%
filter(!is.na(Group)) # Keep only patients with clinical data
# Response by treatment group
crosstable(
data = combined_data,
vars = "RECIST_Response",
group = "Group"
)
Response Kinetics Analysis
Response Magnitude Analysis
# Analyze response magnitude by patient subgroups
response_magnitude <- combined_data %>%
filter(!is.na(ResponseValue)) %>%
mutate(
Age_Group = case_when(
Age < 50 ~ "< 50 years",
Age >= 50 ~ "≥ 50 years"
),
High_Grade = ifelse(Grade == "3", "Grade 3", "Grade 1-2")
)
# Response by age group
summarydata(
data = response_magnitude,
vars = "ResponseValue",
date_vars = NULL,
grvar = "Age_Group"
)
# Response by tumor grade
summarydata(
data = response_magnitude,
vars = "ResponseValue",
date_vars = NULL,
grvar = "High_Grade"
)
Predictive Biomarker Analysis
# Merge with biomarker data
biomarker_response <- combined_data %>%
left_join(
histopathology %>%
select(ID, MeasurementA, MeasurementB) %>%
mutate(PatientID = paste0("PT", sprintf("%04d", ID))),
by = "PatientID"
) %>%
filter(!is.na(MeasurementA) & !is.na(ResponseValue)) %>%
mutate(
MeasurementA_Level = ifelse(MeasurementA > median(MeasurementA), "High", "Low"),
MeasurementB_Level = ifelse(MeasurementB > median(MeasurementB), "High", "Low")
)
# Response by biomarker levels
crosstable(
data = biomarker_response,
vars = "RECIST_Response",
group = "MeasurementA_Level"
)
Response Duration Analysis
# Create response duration data
duration_data <- combined_data %>%
filter(!is.na(ResponseValue)) %>%
left_join(
histopathology %>%
select(ID, OverallTime) %>%
mutate(PatientID = paste0("PT", sprintf("%04d", ID))),
by = "PatientID"
) %>%
filter(!is.na(OverallTime))
# Duration by response category
summarydata(
data = duration_data,
vars = "OverallTime",
date_vars = NULL,
grvar = "RECIST_Response"
)
Clinical Significance Assessment
Response Rate Calculations
# Calculate response rates by subgroup
response_rates <- combined_data %>%
filter(!is.na(RECIST_Response) & RECIST_Response != "Not Evaluable") %>%
group_by(Group) %>%
summarise(
Total_Patients = n(),
PR_Count = sum(RECIST_Response == "Partial Response (PR)"),
SD_Count = sum(RECIST_Response == "Stable Disease (SD)"),
PD_Count = sum(RECIST_Response == "Progressive Disease (PD)"),
Overall_Response_Rate = round(PR_Count / Total_Patients * 100, 1),
Disease_Control_Rate = round((PR_Count + SD_Count) / Total_Patients * 100, 1),
Progressive_Disease_Rate = round(PD_Count / Total_Patients * 100, 1),
.groups = 'drop'
)
kable(response_rates,
caption = "Treatment Response Rates by Study Group",
col.names = c("Group", "Total", "PR", "SD", "PD",
"ORR (%)", "DCR (%)", "PDR (%)"))
Best Response Analysis
# Analyze best response categories
best_response_summary <- combined_data %>%
filter(!is.na(Best_Response)) %>%
group_by(Group, Best_Response) %>%
summarise(Count = n(), .groups = 'drop') %>%
group_by(Group) %>%
mutate(Percentage = round(Count / sum(Count) * 100, 1)) %>%
arrange(Group, desc(Count))
kable(best_response_summary,
caption = "Best Response Distribution by Treatment Group")
Conclusions and Clinical Implications
Key Findings Summary
Based on this comprehensive treatment response analysis:
- Overall Response: The analysis reveals distinct response patterns between treatment groups
- RECIST Classification: Standard RECIST criteria provide clear categorization of responses
- Predictive Factors: Age, grade, and biomarker levels show associations with response
- Clinical Benefit: Disease control rates demonstrate treatment efficacy beyond just partial responses
Visualization Strengths
- Waterfall Plots: Excellent for visualizing individual patient responses and overall treatment effect
-
Swimmer Plots: Essential for understanding
treatment duration and timeline relationships
- Combined Analysis: Integration with pathological and biomarker data enhances clinical relevance
Implementation in jamovi
All response analysis functions are available in jamovi:
-
Waterfall Plots:
Exploration > Patient Follow-Up Plots > Treatment Response Analysis
-
Swimmer Plots:
Exploration > Patient Follow-Up Plots > Swimmer Plot
-
Cross-tabulations:
Exploration > ClinicoPath Comparisons > Cross Tables
The jamovi interface provides point-and-click access to these specialized oncology analysis tools, making them accessible to clinical researchers without programming experience.