---
title: 'CGIP of Younger Patients with NSCLC'
author: 'Zachary D Wallen'
date: '`r format(Sys.time(), "Last modified: %d %B %Y")`'
output:
  bookdown::html_notebook2: 
    toc: yes
    depth: 5
    highlight: pygments
---

# Setting up R environment 

## Create needed functions

```{r functions}
# Function to suppress warnings and messages
# parameters:
#     x - the command to suppress messages/warnings of
suppress <- function(x) {
  invisible(capture.output(suppressMessages(suppressWarnings(x))))
}

# Function to convert numbers from strings back to numbers in excel output
# parameters:
#       df - the data.frame being outputted into excel
#       wb - the excel workbook object
#    sheet - the excel sheet name
# colnames - does df have column names, TRUE/FALSE
convertNum <- function(df, wb, sheet, colnames) {
  library(foreach)
  cn <- expand.grid(seq_len(ncol(df)), seq_len(nrow(df)))[, 1]
  rn <- expand.grid(seq_len(ncol(df)), seq_len(nrow(df)))[, 2]
  trash <- foreach(cn = cn, rn = rn) %dopar% {
    if (!is.numeric(df[rn, cn]) && !is.na(as.numeric(as.character(df[rn, cn])))) {
      row.offset <- ifelse(colnames, 1, 0)
      if (df[rn, cn] == Inf) {
        openxlsx::writeData(wb, sheet, "Inf", startCol = cn, startRow = row.offset + rn)
      } else {
        openxlsx::writeData(wb, sheet, as.numeric(as.character(df[rn, cn])),
          startCol = cn, startRow = row.offset + rn
        )
      }
    }
  }
}

# Function to sort a matrix for better visualization of mutual exclusivity
# of alterations across samples
# Retrieved from https://gist.github.com/armish/564a65ab874a770e2c26, and modified
# to work with character, binary, or logical matrices where NA, '', 0, or FALSE
# represents the absence of alterations in a gene
# parameters:
#      M - an alteration by sample matrix
memoSort <- function(M) {
  geneOrder <- sort(
    rowSums(!is.na(M) & M != "" & M > 0 & M != FALSE),
    decreasing = TRUE, index.return = TRUE
  )$ix
  scoreCol <- function(x) {
    score <- 0
    for (i in 1:length(x)) {
      if (!is.na(x[i]) & x[i] != "" & x[i] > 0 & x[i] != FALSE) {
        score <- score + 2^(length(x) - i)
      }
    }
    return(score)
  }
  scores <- apply(M[geneOrder, ], 2, scoreCol)
  sampleOrder <- sort(scores, decreasing = TRUE, index.return = TRUE)$ix
  return(M[geneOrder, sampleOrder])
}

# Function to perform association testing between each level of a categorical variable and
# one or more binary variables describing different group strata. Performs Fisher's
# exact test when no covariates are specified, and Firth's logistic regression (via the
# logistf functionin the logistf package) when covariates are specified.
# parameters:
#       var - column name of the target categorical variable to test
#    strata - a vector of categorical variable column names denoting different strata
#       ref - a vector specifying the reference level for each group specified with strata
#             (only used when performing Firth's logisitic regression)
#    covars - a vector of variable names to include as covariates in testing
# trend.var - column name of a variable to use for performing a test of trend across strata
#   data.df - a data.frame containing the variables to be included in testing
catStratTest <- function(var, strata, ref = NULL, covars = NULL, trend.var = NULL, data.df) {
  # prepare lists for output
  n <- list()
  stats <- list()
  or <- list()
  p <- list()

  # perform testing and summary statistic calculations for each test variables
  for (i in strata) {
    i <- as.character(i)

    # calculate frequency table and total N
    df <- table(data.df[, var], data.df[, i])
    n[[i]] <- colSums(df)

    # for each level of the target variable...
    for (j in rownames(df)) {
      j <- as.character(j)

      # calculate frequency table for presence and absence of current level
      df2 <- table(ifelse(data.df[, var] == j, 0, 1), data.df[, i])

      # calculate summary statistics
      stats[[i]][j] <- list(apply(df2, 2, function(x) {
        paste(x, " ", "(", round(x / sum(x) * 100, 1), "%", ")", sep = "")
      }))

      if (!is.null(covars)) {
        # perform Firth's logistic regression
        res <- logistf::logistf(
          ifelse(data.df[, var] == j, 1, 0) ~ .,
          data = data.frame(
            x = ifelse(data.df[, i] == ref[which(strata == i)], " ", data.df[, i]),
            data.df[, covars, drop = FALSE]
          )
        )
        or[[i]][j] <- list(paste(
          round(exp(res$coefficients[2]), 2),
          " [", round(exp(res$ci.lower[2]), 2), "; ",
          round(exp(res$ci.upper[2]), 2), "]",
          sep = ""
        ))
        p[[i]][j] <- list(formatC(res$prob[2], digits = 1, format = "e"))
      } else {
        # perform Fisher's exact test
        res <- fisher.test(df2)
        or[[i]][j] <- list(paste(
          round(res$estimate, 2),
          " [", round(res$conf.int[1], 2), "; ",
          round(res$conf.int[2], 2), "]",
          sep = ""
        ))
        p[[i]][j] <- list(formatC(res$p.value, digits = 1, format = "e"))
      }
    }
  }

  # if provided, perform test for trend for each variable level using the trend variable
  if (!is.null(trend.var)) {
    ptrend <- c()
    for (j in seq_along(names(table(data.df[, var])))) {
      if (!is.null(covars)) {
        ptrend <- c(ptrend, as.vector(
          anova(
            logistf::logistf(
              ifelse(
                data.df[, var] == names(table(data.df[, var]))[j], 1, 0
              ) ~ .,
              data = data.df[, c(trend.var, covars)]
            ),
            logistf::logistf(
              ifelse(
                data.df[, var] == names(table(data.df[, var]))[j], 1, 0
              ) ~ .,
              data = data.df[, covars, drop = FALSE]
            ),
            method = "PLR"
          )$pval
        ))
        names(ptrend)[j] <- names(table(data.df[, var]))[j]
      } else {
        ptrend <- c(ptrend, as.vector(
          anova(
            logistf::logistf(
              ifelse(
                data.df[, var] == names(table(data.df[, var]))[j], 1, 0
              ) ~ data.df[, trend.var]
            ),
            logistf::logistf(
              ifelse(
                data.df[, var] == names(table(data.df[, var]))[j], 1, 0
              ) ~ 1
            ),
            method = "PLR"
          )$pval
        ))
        names(ptrend)[j] <- names(table(data.df[, var]))[j]
      }
    }
  } else {
    ptrend <- NULL
  }
  return(list(n = n, stats = stats, or = or, p = p, ptrend = ptrend))
}

# Function to perform association testing between a quantitative variable and
# one or more binary variables describing different group strata. Performs linear
# regression with or without adjustment for covariates.
# parameters:
#       var - column name of the target quantitative variable to test
#    strata - a vector of categorical variable column names denoting different strata
#       ref - a vector specifying the reference level for each group specified with strata
#    covars - a vector of variable names to include as covariates in testing
# trend.var - column name of a variable to use for performing a test of trend across strata
#   data.df - a data.frame containing the variables to be included in testing
quantStratTest <- function(var, strata, ref, covars = NULL, trend.var = NULL, data.df) {
  # prepare lists for output
  n <- list()
  stats <- list()
  beta <- list()
  p <- list()

  # perform testing and summary statistic calculations for each test variables
  for (i in strata) {
    i <- as.character(i)

    # calculate summary statistics
    df <- ddply(
      data.df, i,
      .fun = function(x) {
        c(
          n = length(na.omit(x[, var])),
          mean = mean(na.omit(x[, var])),
          sd = sd(na.omit(x[, var]))
        )
      }
    )
    n[[i]] <- df$n
    names(n[[i]]) <- df[, i]
    stats[[i]] <- paste(round(df$mean, 1), round(df$sd, 1), sep = "±")
    names(stats[[i]]) <- df[, i]

    # perform linear regression with or without covariates
    if (!is.null(covars)) {
      res <- lm(
        data.df[, var] ~ .,
        data = data.frame(
          x = ifelse(data.df[, i] == ref[which(strata == i)], " ", data.df[, i]),
          data.df[, covars, drop = FALSE]
        )
      )
      beta[[i]] <- paste(
        round(summary(res)$coefficients[2, 1], 2),
        " [", round(confint(res)[2, 1], 2), "; ", round(confint(res)[2, 2], 2), "]",
        sep = ""
      )
      p[[i]] <- formatC(summary(res)$coefficients[2, 4], digits = 1, format = "e")
    } else {
      res <- lm(
        data.df[, var] ~ .,
        data = data.frame(
          x = ifelse(data.df[, i] == ref[which(strata == i)], " ", data.df[, i])
        )
      )
      beta[[i]] <- paste(
        round(summary(res)$coefficients[2, 1], 2),
        " [", round(confint(res)[2, 1], 2), "; ", round(confint(res)[2, 2], 2), "]",
        sep = ""
      )
      p[[i]] <- formatC(summary(res)$coefficients[2, 4], digits = 1, format = "e")
    }
  }

  # if provided, perform test for trend using the trend variable
  if (!is.null(trend.var)) {
    if (!is.null(covars)) {
      ptrend <- anova(
        lm(data.df[, var] ~ ., data = data.df[, c(trend.var, covars)]),
        lm(data.df[, var] ~ ., data = data.df[, covars, drop = FALSE])
      )$`Pr(>F)`[2]
    } else {
      ptrend <- anova(
        lm(data.df[, var] ~ ., data = data.df[, trend.var, drop = FALSE]),
        lm(data.df[, var] ~ 1)
      )$`Pr(>F)`[2]
    }
  } else {
    ptrend <- NULL
  }
  return(list(n = n, stats = stats, beta = beta, p = p, ptrend = ptrend))
}
```

## Load required R packages

```{r packages}
suppress(library(plyr))
suppress(library(readxl))
suppress(library(tibble))
suppress(library(openxlsx))
suppress(library(foreach))
suppress(library(kableExtra))
suppress(library(ggplot2))
suppress(library(ggfortify))
suppress(library(ggpubr))
suppress(library(ggtext))
suppress(library(plotly))
suppress(library(GGally))
suppress(library(ggrepel))
suppress(library(ggvenn))
suppress(library(survival))
```

## Create excel styles and color vectors used for formatting output

```{r styles}
bold <- createStyle(textDecoration = "bold")
left_just <- createStyle(halign = "left", valign = "center", wrapText = TRUE)
right_just <- createStyle(halign = "right", valign = "center", wrapText = TRUE)
center <- createStyle(halign = "center", valign = "center", wrapText = TRUE)
horizontal_border_med <- createStyle(border = "top", borderStyle = "medium")
horizontal_border_thin <- createStyle(border = "top", borderStyle = "thin")
percentage <- createStyle(numFmt = "PERCENTAGE")
labcorp.col <- c(
  "#3a5ce9", "#4cd5f7", "#f7758c", "#918f90",
  "#1a2188", "#2998e3", "#6c2fac", "#b4f6f5"
)
```

# Statistical analysis

## Import and prepare data

```{r import-data}
# read data
patient.df <- data.frame(read_xlsx(
  "_Data_for_analysis/CGIP_of_Young_NSCLC_2024_de_id_data.xlsx",
  na = c("NULL", "NA", "N/A"), sheet = 1
))
variant.df <- data.frame(read_xlsx(
  "_Data_for_analysis/CGIP_of_Young_NSCLC_2024_de_id_data.xlsx",
  na = c("NULL", "NA", "N/A"), sheet = 2
))
therapy.df <- data.frame(read_xlsx(
  "_Data_for_analysis/CGIP_of_Young_NSCLC_2024_de_id_data.xlsx",
  na = c("NULL", "NA", "N/A"), sheet = 3
))
immune.df <- data.frame(read_xlsx(
  "_Data_for_analysis/CGIP_of_Young_NSCLC_2024_de_id_data.xlsx",
  na = c("NULL", "NA", "N/A"), sheet = 4
))
gene.list <- data.frame(read_xlsx(
  "_Data_for_analysis/OmniSeq_immune_signature_genelist.xlsx"
), check.names = FALSE)

# remove data for patients with no age data and for hypermutated patients
patient.df <- patient.df[
  !(patient.df$de_id %in% patient.df$de_id[patient.df$TMB > 200]) &
    !is.na(patient.df$patient_age),
]
immune.df <- immune.df[immune.df$de_id %in% patient.df$de_id, ]
therapy.df <- therapy.df[therapy.df$de_id %in% patient.df$de_id, ]
variant.df <- variant.df[variant.df$de_id %in% patient.df$de_id, ]

# order levels of histology groups by decreasing N, then other
patient.df$histology_group <- factor(
  patient.df$histology_group,
  levels = c(
    "Adenocarcinoma", "Squamous cell carcinoma", "Large cell neuroendocrine",
    "Other NSCLC"
  )
)

# order tissue specimen status
patient.df$tissue_status <- factor(
  patient.df$tissue_status,
  levels = c("Primary", "Advanced", "Metastatic")
)

# collapse sub-groups of clinical stages
patient.df$stage[grep("Stage IV|Metastatic", patient.df$stage)] <- "Stage IV"
patient.df$stage[grep("Stage III", patient.df$stage)] <- "Stage III"
patient.df$stage[
  grepl("Stage II", patient.df$stage) & patient.df$stage != "Stage III"
] <- "Stage II"
patient.df$stage[
  grepl("Stage I", patient.df$stage) &
    patient.df$stage != "Stage IV" &
    patient.df$stage != "Stage III" &
    patient.df$stage != "Stage II"
] <- "Stage I"
patient.df$stage[
  is.na(patient.df$stage) | !grepl("Stage I", patient.df$stage)
] <- "Unknown"

# re-create TMB interpretation with very high/high/low
# and make sure to mask TMB score for those that failed testing
patient.df$TMB_interp <- NA
patient.df$TMB_interp[patient.df$TMB >= 20] <- "Very high (≥20)"
patient.df$TMB_interp[patient.df$TMB < 20 & patient.df$TMB >= 10] <- "High (10-19)"
patient.df$TMB_interp[patient.df$TMB < 10] <- "Not high (<10)"
patient.df$TMB_interp[
  patient.df$de_id %in%
    patient.df$de_id[patient.df$DNA_TMB %in% c("Fail", "Not Performed")]
] <- NA
patient.df$TMB[
  patient.df$de_id %in%
    patient.df$de_id[patient.df$DNA_TMB %in% c("Fail", "Not Performed")]
] <- NA
patient.df$TMB_interp <- factor(
  patient.df$TMB_interp,
  levels = c("Not high (<10)", "High (10-19)", "Very high (≥20)")
)

# re-create PD-L1 with high/low/negative and make sure to mask PD-L1 score for those
# that failed testing
patient.df$PD_L1_IHC_22C3_interp <- NA
patient.df$PD_L1_IHC_22C3_interp[
  patient.df$PD_L1_IHC_22C3_result >= 50
] <- "High (≥50%)"
patient.df$PD_L1_IHC_22C3_interp[
  patient.df$PD_L1_IHC_22C3_result < 50 &
    patient.df$PD_L1_IHC_22C3_result >= 1
] <- "Low (1-49%)"
patient.df$PD_L1_IHC_22C3_interp[
  patient.df$PD_L1_IHC_22C3_result == 0
] <- "Negative (<1%)"
patient.df$PD_L1_IHC_22C3_interp[
  patient.df$de_id %in%
    patient.df$de_id[patient.df$PD_L1_IHC_22C3 %in% c("Fail", "Not Performed")]
] <- NA
patient.df$PD_L1_IHC_22C3_result[
  patient.df$de_id %in%
    patient.df$de_id[patient.df$PD_L1_IHC_22C3 %in% c("Fail", "Not Performed")]
] <- NA
patient.df$PD_L1_IHC_22C3_interp <- factor(
  patient.df$PD_L1_IHC_22C3_interp,
  levels = c("Negative (<1%)", "Low (1-49%)", "High (≥50%)")
)

# create variable denoting ALK or EGFR + cases
patient.df$ALK_EGFR <- ifelse(
  patient.df$de_id %in% variant.df$de_id[variant.df$gene %in% c("ALK", "EGFR")], 1, 0
)

# mark gene expression data NA for those who failed RNA expression
immune.df[
  immune.df$de_id %in% patient.df$de_id[patient.df$RNA_Expression %in% c("Fail", "Not Performed")],
  grep("de_id", colnames(immune.df), invert = TRUE)
] <- NA

# recode SNV type variable to make more simple categories and add CNV and Fusion entries
variant.df$snv_type[grep("^Complex|^Nonstop|^Promoter", variant.df$snv_type)] <- "Other SNV"
variant.df$snv_type[grep("^Deletion|^Insertion", variant.df$snv_type)] <- "Indel"
variant.df$snv_type[grep("^Splice", variant.df$snv_type)] <- "Splice site"
variant.df$snv_type[grep("^Substitution", variant.df$snv_type)] <- "Substitution"
variant.df$snv_type[variant.df$variant_type == "CNV"] <- "CNV"
variant.df$snv_type[variant.df$variant_type == "Fusion"] <- "Fusion"

# recode AMP/CAP/ASCO tier variable to only have two categories and be more clear
therapy.df$amp_cap_asco_tier[grep("1", therapy.df$amp_cap_asco_tier)] <- "Guideline indicated"
therapy.df$amp_cap_asco_tier[grep("2", therapy.df$amp_cap_asco_tier)] <- "Clinical trial or therapy in other tumor type"

# create variables to stratify patients by age
patient.df$age_45 <- ifelse(
  patient.df$patient_age < 45, "<45",
  ifelse(patient.df$patient_age >= 65, "≥65", NA)
)
patient.df$age_50 <- ifelse(
  patient.df$patient_age < 50, "<50",
  ifelse(patient.df$patient_age >= 65, "≥65", NA)
)
patient.df$age_55 <- ifelse(
  patient.df$patient_age < 55, "<55",
  ifelse(patient.df$patient_age >= 65, "≥65", NA)
)
patient.df$age_60 <- ifelse(
  patient.df$patient_age < 60, "<60",
  ifelse(patient.df$patient_age >= 65, "≥65", NA)
)
patient.df$age_65 <- ifelse(
  patient.df$patient_age < 65, "<65",
  ifelse(patient.df$patient_age >= 65, "≥65", NA)
)
patient.df$trend_age <- ifelse(
  patient.df$patient_age < 65, patient.df$patient_age,
  ifelse(patient.df$patient_age >= 65, 65, NA)
)
age_strat <- c("age_65", "age_60", "age_55", "age_50", "age_45")

# create variables to stratify patients by gender
patient.df$male <- ifelse(
  patient.df$patient_sex == "Male", 1,
  ifelse(patient.df$patient_sex == "Female", 2, NA)
)
patient.df$female <- ifelse(
  patient.df$patient_sex == "Female", 1,
  ifelse(patient.df$patient_sex == "Male", 2, NA)
)

# add tissue status, gender groups, and age groups to the
# alteration, gene expression, and therapy data
variant.df <- merge(
  patient.df[, c(
    "de_id", "histology_group", "tissue_status", "patient_sex", "male", "female",
    "age_45", "age_50", "age_55", "age_60", "age_65", "trend_age", "ALK_EGFR"
  )],
  variant.df,
  sort = FALSE
)

immune.df <- merge(
  patient.df[, c(
    "de_id", "histology_group", "tissue_status", "patient_sex", "male", "female",
    "age_45", "age_50", "age_55", "age_60", "age_65", "trend_age", "ALK_EGFR"
  )],
  immune.df,
  sort = FALSE
)

therapy.df <- merge(
  patient.df[, c(
    "de_id", "histology_group", "tissue_status", "patient_sex", "male", "female",
    "age_45", "age_50", "age_55", "age_60", "age_65", "trend_age", "ALK_EGFR"
  )],
  therapy.df,
  sort = FALSE
)
```

## Patient characteristics

### Patient numbers

```{r patient-n}
kable(
  data.frame(
    Histology = gsub("Sum", "All patients", names(addmargins(table(patient.df$histology_group)))),
    `Total patients` = paste(
      addmargins(table(patient.df$histology_group)), " (",
      round(addmargins(table(patient.df$histology_group)) /
        addmargins(table(patient.df$histology_group))["Sum"] * 100, 0), "%)",
      sep = ""
    ),
    `Patients with alterations` = paste(
      addmargins(table(patient.df$histology_group[patient.df$de_id %in% variant.df$de_id])), " (",
      round(addmargins(table(patient.df$histology_group[patient.df$de_id %in% variant.df$de_id])) /
        addmargins(table(patient.df$histology_group[patient.df$de_id %in% variant.df$de_id]))["Sum"] * 100, 0), "%)",
      sep = ""
    ),
    check.names = FALSE
  ),
  caption = "Total number of patients by histology group", align = "c",
  col.names = c("Histology", "Total patients", "Patients with alterations")
) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    position = "center", fixed_thead = TRUE, font_size = 12
  )
```
```{r alteration-n}
kable(
  data.frame(
    `Alteration types` = gsub(
      "Sum", "All alteration types",
      rownames(addmargins(table(variant.df$variant_type, variant.df$histology_group)))
    ),
    Adenocarcinoma = paste(
      addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Adenocarcinoma"], " (",
      round(addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Adenocarcinoma"] /
        addmargins(table(variant.df$variant_type, variant.df$histology_group))["Sum", "Adenocarcinoma"] * 100, 0), "%)",
      sep = ""
    ),
    `Squamous cell carcinoma` = paste(
      addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Squamous cell carcinoma"], " (",
      round(addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Squamous cell carcinoma"] /
        addmargins(table(variant.df$variant_type, variant.df$histology_group))["Sum", "Squamous cell carcinoma"] * 100, 0), "%)",
      sep = ""
    ),
    `Large cell neuroendocrine` = paste(
      addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Large cell neuroendocrine"], " (",
      round(addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Large cell neuroendocrine"] /
        addmargins(table(variant.df$variant_type, variant.df$histology_group))["Sum", "Large cell neuroendocrine"] * 100, 0), "%)",
      sep = ""
    ),
    `Other NSCLC` = paste(
      addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Other NSCLC"], " (",
      round(addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Other NSCLC"] /
        addmargins(table(variant.df$variant_type, variant.df$histology_group))["Sum", "Other NSCLC"] * 100, 0), "%)",
      sep = ""
    ),
    `All patients` = paste(
      addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Sum"], " (",
      round(addmargins(table(variant.df$variant_type, variant.df$histology_group))[, "Sum"] /
        addmargins(table(variant.df$variant_type, variant.df$histology_group))["Sum", "Sum"] * 100, 0), "%)",
      sep = ""
    ),
    check.names = FALSE
  ),
  caption = "Number of alterations by histology", align = "c"
) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    position = "center", fixed_thead = TRUE, font_size = 12
  )
```

### Patient demographics and clinical summary statistics

```{r patient-summ-stats}
# create result data.frame
results <- data.frame()
results <- rbind(
  results,
  data.frame(
    Variable = "",
    N = "All patients", `Summary stats` = "",
    N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
    N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
    N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
    N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
    N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
    N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
    Ptrend = "",
    check.names = FALSE
  )
)
results <- rbind(
  results,
  data.frame(
    Variable = "Variable",
    N = "N", `Summary stats` = "Summary stats",
    N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "OR", P1 = "P",
    N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR", P2 = "P",
    N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "OR", P3 = "P",
    N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "OR", P4 = "P",
    N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "OR", P5 = "P",
    N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "OR", P6 = "P",
    Ptrend = "P for trend",
    check.names = FALSE
  )
)

# get total number of patients
results <- rbind(
  results,
  data.frame(
    Variable = "Total number of patients",
    N = nrow(patient.df), `Summary stats` = "-",
    N1 = table(patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
    N2 = table(patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
    N3 = table(patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
    N4 = table(patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
    N5 = table(patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
    N6 = table(patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
    Ptrend = "-",
    check.names = FALSE
  )
)

### gender

# perform testing
var <- "patient_sex"
res <- catStratTest(
  var = var, strata = age_strat, trend.var = "trend_age",
  data.df = patient.df[patient.df[, var] != "Unspecified", ]
)

# get totals for all patients
data.df <- table(
  patient.df[patient.df[, var] != "Unspecified", var],
  rep("0", nrow(patient.df[patient.df[, var] != "Unspecified", ]))
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("Sex (N, %)", rownames(data.df)),
    N = c(sum(data.df), rep("", nrow(data.df))),
    `Summary stats` = c(
      "",
      paste(
        rowSums(data.df), " ", "(", round(rowSums(data.df) / sum(data.df) * 100, 1), "%", ")",
        sep = ""
      )
    ),
    N1 = c(res$n[[1]][2], rep("", nrow(data.df))),
    `N1 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 2]
    })),
    OR1 = c("", "", "Ref"),
    P1 = c("", "", "Ref"),
    N2 = c(res$n[[1]][1], rep("", nrow(data.df))),
    `N2 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 1]
    })),
    OR2 = c("", "", res$or[[1]][[2]][1]),
    P2 = c("", "", res$p[[1]][[2]][1]),
    N3 = c(res$n[[2]][1], rep("", nrow(data.df))),
    `N3 summary stats` = c("", sapply(res$stats[[2]], function(x) {
      x[1, 1]
    })),
    OR3 = c("", "", res$or[[2]][[2]][1]),
    P3 = c("", "", res$p[[2]][[2]][1]),
    N4 = c(res$n[[3]][1], rep("", nrow(data.df))),
    `N4 summary stats` = c("", sapply(res$stats[[3]], function(x) {
      x[1, 1]
    })),
    OR4 = c("", "", res$or[[3]][[2]][1]),
    P4 = c("", "", res$p[[3]][[2]][1]),
    N5 = c(res$n[[4]][1], rep("", nrow(data.df))),
    `N5 summary stats` = c("", sapply(res$stats[[4]], function(x) {
      x[1, 1]
    })),
    OR5 = c("", "", res$or[[4]][[2]][1]),
    P5 = c("", "", res$p[[4]][[2]][1]),
    N6 = c(res$n[[5]][1], rep("", nrow(data.df))),
    `N6 summary stats` = c("", sapply(res$stats[[5]], function(x) {
      x[1, 1]
    })),
    OR6 = c("", "", res$or[[5]][[2]][1]),
    P6 = c("", "", res$p[[5]][[2]][1]),
    Ptrend = c("", "", formatC(res$ptrend[2], digits = 1, format = "e")),
    check.names = FALSE
  )
)

### age

# get summary statistics
var <- "patient_age"
n <- list()
stats <- list()
for (i in seq_along(age_strat)) {
  df <- ddply(
    patient.df, age_strat[i], summarize,
    n = length(na.omit(patient_age)),
    mean = mean(na.omit(patient_age)),
    sd = sd(na.omit(patient_age))
  )
  if (i == 1) {
    n[[i]] <- df$n[2]
    stats[[i]] <- paste(round(df$mean[2], 1), round(df$sd[2], 1), sep = "±")
  }
  n[[i + 1]] <- df$n[1]
  stats[[i + 1]] <- paste(round(df$mean[1], 1), round(df$sd[1], 1), sep = "±")
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "Age (Mean±SD)",
    N = nrow(patient.df),
    `Summary stats` = paste(
      round(mean(patient.df[, var]), 1), round(sd(patient.df[, var]), 1),
      sep = "±"
    ),
    N1 = n[[1]], `N1 summary stats` = stats[[1]], OR1 = "-", P1 = "-",
    N2 = n[[2]], `N2 summary stats` = stats[[2]], OR2 = "-", P2 = "-",
    N3 = n[[3]], `N3 summary stats` = stats[[3]], OR3 = "-", P3 = "-",
    N4 = n[[4]], `N4 summary stats` = stats[[4]], OR4 = "-", P4 = "-",
    N5 = n[[5]], `N5 summary stats` = stats[[5]], OR5 = "-", P5 = "-",
    N6 = n[[6]], `N6 summary stats` = stats[[6]], OR6 = "-", P6 = "-",
    Ptrend = "-",
    check.names = FALSE
  )
)

### histology

# perform testing
var <- "histology_group"
res <- catStratTest(
  var = var, strata = age_strat, trend.var = "trend_age", data.df = patient.df
)

# get totals for all patients
data.df <- table(patient.df[, var], rep("0", nrow(patient.df)))

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("Histology group (N, %)", rownames(data.df)),
    N = c(sum(data.df), rep("", nrow(data.df))),
    `Summary stats` = c(
      "",
      paste(
        rowSums(data.df), " ", "(", round(rowSums(data.df) / sum(data.df) * 100, 1), "%", ")",
        sep = ""
      )
    ),
    N1 = c(res$n[[1]][2], rep("", nrow(data.df))),
    `N1 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 2]
    })),
    OR1 = c("", rep("Ref", nrow(data.df))),
    P1 = c("", rep("Ref", nrow(data.df))),
    N2 = c(res$n[[1]][1], rep("", nrow(data.df))),
    `N2 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 1]
    })),
    OR2 = c("", sapply(res$or[[1]], function(x) {
      x[1]
    })),
    P2 = c("", sapply(res$p[[1]], function(x) {
      x[1]
    })),
    N3 = c(res$n[[2]][1], rep("", nrow(data.df))),
    `N3 summary stats` = c("", sapply(res$stats[[2]], function(x) {
      x[1, 1]
    })),
    OR3 = c("", sapply(res$or[[2]], function(x) {
      x[1]
    })),
    P3 = c("", sapply(res$p[[2]], function(x) {
      x[1]
    })),
    N4 = c(res$n[[3]][1], rep("", nrow(data.df))),
    `N4 summary stats` = c("", sapply(res$stats[[3]], function(x) {
      x[1, 1]
    })),
    OR4 = c("", sapply(res$or[[3]], function(x) {
      x[1]
    })),
    P4 = c("", sapply(res$p[[3]], function(x) {
      x[1]
    })),
    N5 = c(res$n[[4]][1], rep("", nrow(data.df))),
    `N5 summary stats` = c("", sapply(res$stats[[4]], function(x) {
      x[1, 1]
    })),
    OR5 = c("", sapply(res$or[[4]], function(x) {
      x[1]
    })),
    P5 = c("", sapply(res$p[[4]], function(x) {
      x[1]
    })),
    N6 = c(res$n[[5]][1], rep("", nrow(data.df))),
    `N6 summary stats` = c("", sapply(res$stats[[5]], function(x) {
      x[1, 1]
    })),
    OR6 = c("", sapply(res$or[[5]], function(x) {
      x[1]
    })),
    P6 = c("", sapply(res$p[[5]], function(x) {
      x[1]
    })),
    Ptrend = c("", formatC(res$ptrend, digits = 1, format = "e")),
    check.names = FALSE
  )
)

### tumor specimen site

# perform testing
var <- "tissue_status"
res <- catStratTest(
  var = var, strata = age_strat, trend.var = "trend_age", data.df = patient.df
)

# get totals for all patients
data.df <- table(patient.df[, var], rep("0", nrow(patient.df)))

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("Tumor specimen site (N, %)", rownames(data.df)),
    N = c(sum(data.df), rep("", nrow(data.df))),
    `Summary stats` = c(
      "",
      paste(
        rowSums(data.df), " ", "(", round(rowSums(data.df) / sum(data.df) * 100, 1), "%", ")",
        sep = ""
      )
    ),
    N1 = c(res$n[[1]][2], rep("", nrow(data.df))),
    `N1 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 2]
    })),
    OR1 = c("", rep("Ref", nrow(data.df))),
    P1 = c("", rep("Ref", nrow(data.df))),
    N2 = c(res$n[[1]][1], rep("", nrow(data.df))),
    `N2 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 1]
    })),
    OR2 = c("", sapply(res$or[[1]], function(x) {
      x[1]
    })),
    P2 = c("", sapply(res$p[[1]], function(x) {
      x[1]
    })),
    N3 = c(res$n[[2]][1], rep("", nrow(data.df))),
    `N3 summary stats` = c("", sapply(res$stats[[2]], function(x) {
      x[1, 1]
    })),
    OR3 = c("", sapply(res$or[[2]], function(x) {
      x[1]
    })),
    P3 = c("", sapply(res$p[[2]], function(x) {
      x[1]
    })),
    N4 = c(res$n[[3]][1], rep("", nrow(data.df))),
    `N4 summary stats` = c("", sapply(res$stats[[3]], function(x) {
      x[1, 1]
    })),
    OR4 = c("", sapply(res$or[[3]], function(x) {
      x[1]
    })),
    P4 = c("", sapply(res$p[[3]], function(x) {
      x[1]
    })),
    N5 = c(res$n[[4]][1], rep("", nrow(data.df))),
    `N5 summary stats` = c("", sapply(res$stats[[4]], function(x) {
      x[1, 1]
    })),
    OR5 = c("", sapply(res$or[[4]], function(x) {
      x[1]
    })),
    P5 = c("", sapply(res$p[[4]], function(x) {
      x[1]
    })),
    N6 = c(res$n[[5]][1], rep("", nrow(data.df))),
    `N6 summary stats` = c("", sapply(res$stats[[5]], function(x) {
      x[1, 1]
    })),
    OR6 = c("", sapply(res$or[[5]], function(x) {
      x[1]
    })),
    P6 = c("", sapply(res$p[[5]], function(x) {
      x[1]
    })),
    Ptrend = c("", formatC(res$ptrend, digits = 1, format = "e")),
    check.names = FALSE
  )
)

### unknown clinical stage

# get frequencies
data.df <- cbind(
  table(
    factor(
      ifelse(patient.df$stage == "Unknown",
        "Unknown clinical stage (N, %)",
        "Known clinical stage (N, %)"
      ),
      levels = c("Unknown clinical stage (N, %)", "Known clinical stage (N, %)")
    ),
    patient.df$age_65
  )[, 2],
  table(
    factor(
      ifelse(patient.df$stage == "Unknown",
        "Unknown clinical stage (N, %)",
        "Known clinical stage (N, %)"
      ),
      levels = c("Unknown clinical stage (N, %)", "Known clinical stage (N, %)")
    ),
    patient.df$age_65
  )[, 1],
  table(
    factor(
      ifelse(patient.df$stage == "Unknown",
        "Unknown clinical stage (N, %)",
        "Known clinical stage (N, %)"
      ),
      levels = c("Unknown clinical stage (N, %)", "Known clinical stage (N, %)")
    ),
    patient.df$age_60
  )[, 1],
  table(
    factor(
      ifelse(patient.df$stage == "Unknown",
        "Unknown clinical stage (N, %)",
        "Known clinical stage (N, %)"
      ),
      levels = c("Unknown clinical stage (N, %)", "Known clinical stage (N, %)")
    ),
    patient.df$age_55
  )[, 1],
  table(
    factor(
      ifelse(patient.df$stage == "Unknown",
        "Unknown clinical stage (N, %)",
        "Known clinical stage (N, %)"
      ),
      levels = c("Unknown clinical stage (N, %)", "Known clinical stage (N, %)")
    ),
    patient.df$age_50
  )[, 1],
  table(
    factor(
      ifelse(patient.df$stage == "Unknown",
        "Unknown clinical stage (N, %)",
        "Known clinical stage (N, %)"
      ),
      levels = c("Unknown clinical stage (N, %)", "Known clinical stage (N, %)")
    ),
    patient.df$age_45
  )[, 1]
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = rownames(data.df),
    N = rep("", 2),
    `Summary stats` = paste(
      rowSums(data.df[, c(1, 2)]), " ", "(",
      round(rowSums(data.df[, c(1, 2)]) / sum(data.df[, c(1, 2)]) * 100, 1), "%", ")",
      sep = ""
    ),
    N1 = rep("", 2),
    `N1 summary stats` = paste(
      data.df[, 1], " ", "(", round(data.df[, 1] / sum(data.df[, 1]) * 100, 1), "%", ")",
      sep = ""
    ),
    OR1 = rep("-", nrow(data.df)),
    P1 = rep("-", nrow(data.df)),
    N2 = rep("", 2),
    `N2 summary stats` = paste(
      data.df[, 2], " ", "(", round(data.df[, 2] / sum(data.df[, 2]) * 100, 1), "%", ")",
      sep = ""
    ),
    OR2 = rep("-", nrow(data.df)),
    P2 = rep("-", nrow(data.df)),
    N3 = rep("", 2),
    `N3 summary stats` = paste(
      data.df[, 3], " ", "(", round(data.df[, 3] / sum(data.df[, 3]) * 100, 1), "%", ")",
      sep = ""
    ),
    OR3 = rep("-", nrow(data.df)),
    P3 = rep("-", nrow(data.df)),
    N4 = rep("", 2),
    `N4 summary stats` = paste(
      data.df[, 4], " ", "(", round(data.df[, 4] / sum(data.df[, 4]) * 100, 1), "%", ")",
      sep = ""
    ),
    OR4 = rep("-", nrow(data.df)),
    P4 = rep("-", nrow(data.df)),
    N5 = rep("", 2),
    `N5 summary stats` = paste(
      data.df[, 5], " ", "(", round(data.df[, 5] / sum(data.df[, 5]) * 100, 1), "%", ")",
      sep = ""
    ),
    OR5 = rep("-", nrow(data.df)),
    P5 = rep("-", nrow(data.df)),
    N6 = rep("", 2),
    `N6 summary stats` = paste(
      data.df[, 6], " ", "(", round(data.df[, 6] / sum(data.df[, 6]) * 100, 1), "%", ")",
      sep = ""
    ),
    OR6 = rep("-", nrow(data.df)),
    P6 = rep("-", nrow(data.df)),
    Ptrend = rep("-", nrow(data.df)),
    check.names = FALSE
  )
)

### clinical stage

# perform testing
var <- "stage"
res <- catStratTest(
  var = var, strata = age_strat, trend.var = "trend_age",
  data.df = patient.df[patient.df[, var] != "Unknown", ]
)

# get totals for all patients
data.df <- table(
  patient.df[patient.df[, var] != "Unknown", var],
  rep("0", nrow(patient.df[patient.df[, var] != "Unknown", ]))
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("Known clinical stage (N, %)", rownames(data.df)),
    N = c(sum(data.df), rep("", nrow(data.df))),
    `Summary stats` = c(
      "",
      paste(
        rowSums(data.df), " ", "(", round(rowSums(data.df) / sum(data.df) * 100, 1), "%", ")",
        sep = ""
      )
    ),
    N1 = c(res$n[[1]][2], rep("", nrow(data.df))),
    `N1 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 2]
    })),
    OR1 = c("", rep("Ref", nrow(data.df))),
    P1 = c("", rep("Ref", nrow(data.df))),
    N2 = c(res$n[[1]][1], rep("", nrow(data.df))),
    `N2 summary stats` = c("", sapply(res$stats[[1]], function(x) {
      x[1, 1]
    })),
    OR2 = c("", sapply(res$or[[1]], function(x) {
      x[1]
    })),
    P2 = c("", sapply(res$p[[1]], function(x) {
      x[1]
    })),
    N3 = c(res$n[[2]][1], rep("", nrow(data.df))),
    `N3 summary stats` = c("", sapply(res$stats[[2]], function(x) {
      x[1, 1]
    })),
    OR3 = c("", sapply(res$or[[2]], function(x) {
      x[1]
    })),
    P3 = c("", sapply(res$p[[2]], function(x) {
      x[1]
    })),
    N4 = c(res$n[[3]][1], rep("", nrow(data.df))),
    `N4 summary stats` = c("", sapply(res$stats[[3]], function(x) {
      x[1, 1]
    })),
    OR4 = c("", sapply(res$or[[3]], function(x) {
      x[1]
    })),
    P4 = c("", sapply(res$p[[3]], function(x) {
      x[1]
    })),
    N5 = c(res$n[[4]][1], rep("", nrow(data.df))),
    `N5 summary stats` = c("", sapply(res$stats[[4]], function(x) {
      x[1, 1]
    })),
    OR5 = c("", sapply(res$or[[4]], function(x) {
      x[1]
    })),
    P5 = c("", sapply(res$p[[4]], function(x) {
      x[1]
    })),
    N6 = c(res$n[[5]][1], rep("", nrow(data.df))),
    `N6 summary stats` = c("", sapply(res$stats[[5]], function(x) {
      x[1, 1]
    })),
    OR6 = c("", sapply(res$or[[5]], function(x) {
      x[1]
    })),
    P6 = c("", sapply(res$p[[5]], function(x) {
      x[1]
    })),
    Ptrend = c("", formatC(res$ptrend, digits = 1, format = "e")),
    check.names = FALSE
  )
)

### Number of detected alterations

# create data for testing
test.data <- rbind(
  merge(
    patient.df[
      !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
        patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
        patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")),
      c(
        "de_id", "tissue_status", "histology_group",
        grep("^age_|^trend_", colnames(patient.df), value = TRUE)
      )
    ],
    ddply(variant.df, .(de_id), summarize, var_count = length(de_id)),
    by = "de_id"
  ),
  data.frame(
    patient.df[
      !(patient.df$de_id %in% variant.df$de_id) &
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")),
      c(
        "de_id", "tissue_status", "histology_group",
        grep("^age_|^trend_", colnames(patient.df), value = TRUE)
      )
    ],
    var_count = 0
  )
)

# perform testing
var <- "var_count"
ref <- rep("≥65", length(age_strat))
res <- quantStratTest(
  var = var, strata = age_strat, ref = ref,
  covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
  data.df = test.data
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "Number of detected alterations (Mean±SD)",
    N = nrow(test.data[!is.na(test.data[, var]), ]),
    `Summary stats` = paste(
      round(mean(na.omit(test.data[, var])), 1),
      round(sd(na.omit(test.data[, var])), 1),
      sep = "±"
    ),
    N1 = res$n[[1]][2],
    `N1 summary stats` = res$stats[[1]][2],
    OR1 = "Ref",
    P1 = "Ref",
    N2 = res$n[[1]][1],
    `N2 summary stats` = res$stats[[1]][1],
    OR2 = res$beta[[1]],
    P2 = res$p[[1]],
    N3 = res$n[[2]][1],
    `N3 summary stats` = res$stats[[2]][1],
    OR3 = res$beta[[2]],
    P3 = res$p[[2]],
    N4 = res$n[[3]][1],
    `N4 summary stats` = res$stats[[3]][1],
    OR4 = res$beta[[3]],
    P4 = res$p[[3]],
    N5 = res$n[[4]][1],
    `N5 summary stats` = res$stats[[4]][1],
    OR5 = res$beta[[4]],
    P5 = res$p[[4]],
    N6 = res$n[[5]][1],
    `N6 summary stats` = res$stats[[5]][1],
    OR6 = res$beta[[5]],
    P6 = res$p[[5]],
    Ptrend = formatC(res$ptrend, digits = 1, format = "e"),
    check.names = FALSE
  )
)

### Tier 1 or 2 genomic alterations

# create data for testing
test.data <- merge(
  test.data,
  data.frame(
    de_id = patient.df$de_id,
    `Guideline indicated` = ifelse(
      patient.df$de_id %in% therapy.df$de_id[
        grepl("Guideline", therapy.df$amp_cap_asco_tier) &
          therapy.df$marker_component_marker_type %in% c("SNV", "CNV", "Fusion")
      ] &
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")), 0,
      ifelse(
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")),
        1, NA
      )
    ),
    `Clinical trial or therapy in other tumor type` = ifelse(
      patient.df$de_id %in% therapy.df$de_id[
        grepl("Clinical", therapy.df$amp_cap_asco_tier) &
          therapy.df$marker_component_marker_type %in% c("SNV", "CNV", "Fusion")
      ] &
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")), 0,
      ifelse(
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")),
        1, NA
      )
    ),
    `Neither above, but known pathogenic` = ifelse(
      !(patient.df$de_id %in% therapy.df$de_id[
        therapy.df$marker_component_marker_type %in% c("SNV", "CNV", "Fusion")
      ]) &
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")), 0,
      ifelse(
        !(patient.df$DNA_SNV %in% c("Fail", "Not Performed") |
          patient.df$DNA_CNV %in% c("Fail", "Not Performed") |
          patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")),
        1, NA
      )
    ),
    check.names = FALSE
  )
)

# perform testing
var <- c("Guideline indicated", "Clinical trial or therapy in other tumor type", "Neither above, but known pathogenic")
ref <- rep("≥65", length(age_strat))
res <- list()
for (j in var) {
  res[[j]] <- catStratTest(
    var = j, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("Genomic alterations with known or potential clinical significance (N, %)", var),
    N = c(nrow(test.data), rep("", length(var))),
    `Summary stats` = c(
      "",
      paste(
        colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
        round(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
            nrow(test.data) * 100, 1
        ), "%", ")",
        sep = ""
      )
    ),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][2]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][3]
    })),
    OR1 = c("", rep("Ref", length(var))),
    P1 = c("", rep("Ref", length(var))),
    N2 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][1]
    })),
    OR2 = c("", sapply(res, function(x) {
      x$or[[1]][[1]][1]
    })),
    P2 = c("", sapply(res, function(x) {
      x$p[[1]][[1]][1]
    })),
    N3 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N3 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]][1]
    })),
    OR3 = c("", sapply(res, function(x) {
      x$or[[2]][[1]][1]
    })),
    P3 = c("", sapply(res, function(x) {
      x$p[[2]][[1]][1]
    })),
    N4 = c(sapply(res, function(x) {
      x$n[[3]][1]
    })[1], rep("", length(var))),
    `N4 summary stats` = c("", sapply(res, function(x) {
      x$stats[[3]][[1]][1]
    })),
    OR4 = c("", sapply(res, function(x) {
      x$or[[3]][[1]][1]
    })),
    P4 = c("", sapply(res, function(x) {
      x$p[[3]][[1]][1]
    })),
    N5 = c(sapply(res, function(x) {
      x$n[[4]][1]
    })[1], rep("", length(var))),
    `N5 summary stats` = c("", sapply(res, function(x) {
      x$stats[[4]][[1]][1]
    })),
    OR5 = c("", sapply(res, function(x) {
      x$or[[4]][[1]][1]
    })),
    P5 = c("", sapply(res, function(x) {
      x$p[[4]][[1]][1]
    })),
    N6 = c(sapply(res, function(x) {
      x$n[[5]][1]
    })[1], rep("", length(var))),
    `N6 summary stats` = c("", sapply(res, function(x) {
      x$stats[[5]][[1]][1]
    })),
    OR6 = c("", sapply(res, function(x) {
      x$or[[5]][[1]][1]
    })),
    P6 = c("", sapply(res, function(x) {
      x$p[[5]][[1]][1]
    })),
    Ptrend = c("", formatC(sapply(res, function(x) {
      x$ptrend[1]
    }), digits = 1, format = "e")),
    check.names = FALSE
  )
)

### write out results

# create workbook
wb <- createWorkbook()

# add worksheet, write data, and format output
addWorksheet(wb, "Patient characteristics")

writeData(wb, "Patient characteristics", results, keepNA = TRUE, colNames = FALSE)

setColWidths(
  wb, "Patient characteristics",
  cols = seq_len(ncol(results)),
  widths = c(41, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
)

addStyle(
  wb, "Patient characteristics",
  cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
  gridExpand = TRUE, style = left_just, stack = TRUE
)

addStyle(
  wb, "Patient characteristics",
  cols = 1,
  rows = c(
    which(results$Variable == "Female"):which(results$Variable == "Male"),
    which(results$Variable == "Adenocarcinoma"):which(results$Variable == "Other NSCLC"),
    which(results$Variable == "Primary"):which(results$Variable == "Metastatic"),
    which(results$Variable == "Stage I"):which(results$Variable == "Stage IV"),
    which(results$Variable == "Guideline indicated"):which(results$Variable == "Neither above, but known pathogenic")
  ),
  gridExpand = TRUE, style = center, stack = TRUE
)

mergeCells(wb, "Patient characteristics", cols = c(2, 3), rows = 1)
mergeCells(wb, "Patient characteristics", cols = c(4:7), rows = 1)
mergeCells(wb, "Patient characteristics", cols = c(8:11), rows = 1)
mergeCells(wb, "Patient characteristics", cols = c(12:15), rows = 1)
mergeCells(wb, "Patient characteristics", cols = c(16:19), rows = 1)
mergeCells(wb, "Patient characteristics", cols = c(20:23), rows = 1)
mergeCells(wb, "Patient characteristics", cols = c(24:27), rows = 1)

addStyle(
  wb, "Patient characteristics",
  cols = seq_len(ncol(results)), rows = 1:2,
  gridExpand = TRUE, style = bold, stack = TRUE
)

addStyle(
  wb, "Patient characteristics",
  cols = seq_len(ncol(results)),
  rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
  style = horizontal_border_med, stack = TRUE
)

addStyle(
  wb, "Patient characteristics",
  cols = seq_len(ncol(results)),
  rows = c(
    grep("Sex", results$Variable),
    grep("Age \\(", results$Variable),
    grep("Histology", results$Variable),
    grep("Unknown", results$Variable),
    grep("Known", results$Variable)[2],
    grep("Tumor", results$Variable),
    grep("Number", results$Variable),
    grep("Genomic", results$Variable)
  ),
  gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
)

# convert numbers from strings back to numbers
convertNum(results, wb, "Patient characteristics", FALSE)

# save workbook
saveWorkbook(wb, "1_Patient_characteristics/Patient_characteristics.xlsx", overwrite = TRUE)
```

## Genomic alteration prevalence

### Gene-level

```{r gene-level-prevalence}
# define groups to run analyses for
groups <- c("All patients", "Male", "Female")
file.names <- c("all_patients", "males", "females")

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      N = "All patients", Frequency = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Gene",
      N = "N", Frequency = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "OR", P1 = "FDR q-value",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR", P2 = "FDR q-value",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "OR", P3 = "FDR q-value",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "OR", P4 = "FDR q-value",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "OR", P5 = "FDR q-value",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "OR", P6 = "FDR q-value",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      N = nrow(sub.patient.df), Frequency = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  ### SNVs

  # create data for testing
  total.patients <- sum(!(patient.df$DNA_SNV %in% c("Fail", "Not Performed")))
  var <- c()
  test.data <- sub.patient.df
  ref.data <- variant.df[variant.df$variant_type == "SNV", ]
  for (j in unique(ref.data$gene)) {
    test.data$feat <- ifelse(
      sub.patient.df$de_id %in% ref.data$de_id[ref.data$gene == j], 0,
      ifelse(
        !(sub.patient.df$DNA_SNV %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    if (sum(na.omit(test.data$feat == 0)) >= 5) {
      var <- append(var, j)
      colnames(test.data)[ncol(test.data)] <- j
    } else {
      test.data <- test.data[, -ncol(test.data)]
    }
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Single nucleotide variants (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### CNVs

  # create data for testing
  total.patients <- sum(!(patient.df$DNA_CNV %in% c("Fail", "Not Performed")))
  var <- c()
  test.data <- sub.patient.df
  ref.data <- variant.df[variant.df$variant_type == "CNV", ]
  for (j in unique(ref.data$gene)) {
    test.data$feat <- ifelse(
      sub.patient.df$de_id %in% ref.data$de_id[ref.data$gene == j], 0,
      ifelse(
        !(sub.patient.df$DNA_CNV %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    if (sum(na.omit(test.data$feat == 0)) >= 5) {
      var <- append(var, j)
      colnames(test.data)[ncol(test.data)] <- j
    } else {
      test.data <- test.data[, -ncol(test.data)]
    }
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Copy number variants (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### Fusions

  # create data for testing
  total.patients <- sum(!(patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")))
  var <- c()
  test.data <- sub.patient.df
  ref.data <- variant.df[variant.df$variant_type == "Fusion", ]
  ref.data$gene[
    grep("Skip", ref.data$variant_go_name)
  ] <- grep("Skip", ref.data$variant_go_name, value = TRUE)
  for (j in unique(ref.data$gene)) {
    test.data$feat <- ifelse(
      sub.patient.df$de_id %in% ref.data$de_id[ref.data$gene == j], 0,
      ifelse(
        !(sub.patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    if (sum(na.omit(test.data$feat == 0)) >= 5) {
      var <- append(var, j)
      colnames(test.data)[ncol(test.data)] <- j
    } else {
      test.data <- test.data[, -ncol(test.data)]
    }
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Fusions/Skipping Variants (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### multiple testing correction

  # adjust p-values for multiple testing
  for (j in grep("P", colnames(results))) {
    if (colnames(results)[j] != "P1") {
      results[!(results[, j] %in%
        c("FDR q-value", "P for trend", "-", "")), j] <- formatC(
        p.adjust(
          as.numeric(results[!(results[, j] %in%
            c("FDR q-value", "P for trend", "-", "")), j]),
          method = "BH"
        ),
        digits = 1, format = "e"
      )
    }
  }

  ### write out results

  # create workbook
  if (i == 1) {
    wb <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb, groups[i])

  writeData(wb, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(33, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = 1,
    rows = c(
      (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1),
      (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1),
      (grep("^Fusions", results$Variable) + 1):nrow(results)
    ),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb, groups[i], cols = c(2, 3), rows = 1)
  mergeCells(wb, groups[i], cols = c(4:7), rows = 1)
  mergeCells(wb, groups[i], cols = c(8:11), rows = 1)
  mergeCells(wb, groups[i], cols = c(12:15), rows = 1)
  mergeCells(wb, groups[i], cols = c(16:19), rows = 1)
  mergeCells(wb, groups[i], cols = c(20:23), rows = 1)
  mergeCells(wb, groups[i], cols = c(24:27), rows = 1)

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(
      grep("^Single", results$Variable),
      grep("^Copy", results$Variable),
      grep("^Fusions", results$Variable)
    ),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb, groups[i], FALSE)

  # save workbook
  saveWorkbook(
    wb, "2_Genomic_alterations/Patient_alteration_prevalence_by_gene.xlsx",
    overwrite = TRUE
  )

  # plot significant results
  plot.data <- rbind(
    data.frame(
      `Age group` = c(
        rep(
          "≥65",
          length((grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[1],
          length((grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[2],
          length((grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[3],
          length((grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[4],
          length((grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[5],
          length((grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1))
        )
      ),
      Alteration = "SNV",
      Gene = rep(
        results$Variable[
          (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
        ],
        length(age_strat) + 1
      ),
      Frequency = c(
        as.numeric(sapply(
          strsplit(results$`N1 summary stats`[
            (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N2 summary stats`[
            (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N3 summary stats`[
            (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N4 summary stats`[
            (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N5 summary stats`[
            (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N6 summary stats`[
            (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        ))
      ),
      P = rep(
        as.numeric(results$Ptrend[
          (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1)
        ]), length(age_strat) + 1
      ),
      check.names = FALSE
    ),
    data.frame(
      `Age group` = c(
        rep(
          "≥65",
          length((grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[1],
          length((grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[2],
          length((grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[3],
          length((grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[4],
          length((grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1))
        ),
        rep(
          gsub("age_", "<", age_strat)[5],
          length((grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1))
        )
      ),
      Alteration = "CNV",
      Gene = rep(
        results$Variable[
          (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
        ], length(age_strat) + 1
      ),
      Frequency = c(
        as.numeric(sapply(
          strsplit(results$`N1 summary stats`[
            (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N2 summary stats`[
            (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N3 summary stats`[
            (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N4 summary stats`[
            (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N5 summary stats`[
            (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N6 summary stats`[
            (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        ))
      ),
      P = rep(
        as.numeric(results$Ptrend[
          (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1)
        ]), length(age_strat) + 1
      ),
      check.names = FALSE
    ),
    data.frame(
      `Age group` = c(
        rep(
          "≥65",
          length((grep("^Fusions", results$Variable) + 1):nrow(results))
        ),
        rep(
          gsub("age_", "<", age_strat)[1],
          length((grep("^Fusions", results$Variable) + 1):nrow(results))
        ),
        rep(
          gsub("age_", "<", age_strat)[2],
          length((grep("^Fusions", results$Variable) + 1):nrow(results))
        ),
        rep(
          gsub("age_", "<", age_strat)[3],
          length((grep("^Fusions", results$Variable) + 1):nrow(results))
        ),
        rep(
          gsub("age_", "<", age_strat)[4],
          length((grep("^Fusions", results$Variable) + 1):nrow(results))
        ),
        rep(
          gsub("age_", "<", age_strat)[5],
          length((grep("^Fusions", results$Variable) + 1):nrow(results))
        )
      ),
      Alteration = "Fusions/skipping variants",
      Gene = rep(
        results$Variable[
          (grep("^Fusions", results$Variable) + 1):nrow(results)
        ], length(age_strat) + 1
      ),
      Frequency = c(
        as.numeric(sapply(
          strsplit(results$`N1 summary stats`[
            (grep("^Fusions", results$Variable) + 1):nrow(results)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N2 summary stats`[
            (grep("^Fusions", results$Variable) + 1):nrow(results)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N3 summary stats`[
            (grep("^Fusions", results$Variable) + 1):nrow(results)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N4 summary stats`[
            (grep("^Fusions", results$Variable) + 1):nrow(results)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N5 summary stats`[
            (grep("^Fusions", results$Variable) + 1):nrow(results)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        )),
        as.numeric(sapply(
          strsplit(results$`N6 summary stats`[
            (grep("^Fusions", results$Variable) + 1):nrow(results)
          ], "\\("), function(x) {
            strsplit(x[2], "%")[[1]][1]
          }
        ))
      ),
      P = rep(
        as.numeric(results$Ptrend[
          (grep("^Fusions", results$Variable) + 1):nrow(results)
        ]), length(age_strat) + 1
      ),
      check.names = FALSE
    )
  )
  plot.data <- plot.data[plot.data$P <= 0.25 & !is.na(plot.data$P), ]
  plot.data$Alteration <- factor(
    plot.data$Alteration,
    levels = c("SNV", "CNV", "Fusions/skipping variants")
  )
  plot.data$Gene <- factor(plot.data$Gene, levels = rev(unique(plot.data$Gene)))

  g <- ggplot(data = plot.data, aes(x = Gene, y = Frequency, fill = `Age group`)) +
    geom_bar(stat = "identity", position = "dodge", color = "black") +
    geom_text(
      aes(label = paste(Frequency, "%", sep = "")),
      position = position_dodge(width = 0.9), size = 3, hjust = -0.1
    ) +
    scale_x_discrete(labels = scales::wrap_format(15)) +
    scale_y_continuous(position = "right", limits = c(0, max(plot.data$Frequency) + 10)) +
    scale_fill_manual(
      labels = c(names(table(plot.data$`Age group`))[1:5], expression("" >= 65)),
      values = colorRampPalette(c(labcorp.col[8], labcorp.col[1]))(length(age_strat) + 1)
    ) +
    scale_color_manual(values = rep("black", length(age_strat) + 1)) +
    facet_grid(Alteration ~ ., scale = "free", space = "free") +
    coord_flip() +
    theme_bw() +
    labs(y = "Prevalence (%)", x = "Genomic alteration") +
    guides(fill = guide_legend(override.aes = list(shape = NA), reverse = TRUE)) +
    theme(
      text = element_text(size = 14),
      axis.ticks.x = element_blank(), axis.text.x = element_blank()
    )
  ggsave(
    paste("2_Genomic_alterations/Alteration_associations_gene_", file.names[i], ".pdf", sep = ""),
    g,
    device = "pdf", width = 5, height = length(unique(plot.data$Gene))
  )

  # save significant genes for later
  if (i == 1){
    sig.genes <- unique(plot.data$Gene)
  }else{
    sig.genes <- unique(append(sig.genes, unique(plot.data$Gene)))
  }
}
```

### Variant-level

```{r variant-level-prevalence}
# define groups to run analyses for
groups <- c("All patients", "Male", "Female")
file.names <- c("all_patients", "males", "females")

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      Type = "",
      N = "All patients", Frequency = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Variant",
      Type = "SNV type",
      N = "N", Frequency = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "OR", P1 = "FDR q-value",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR", P2 = "FDR q-value",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "OR", P3 = "FDR q-value",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "OR", P4 = "FDR q-value",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "OR", P5 = "FDR q-value",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "OR", P6 = "FDR q-value",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      Type = "",
      N = nrow(sub.patient.df), Frequency = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  ### SNVs

  # create data for testing
  total.patients <- sum(!(patient.df$DNA_SNV %in% c("Fail", "Not Performed")))
  var <- c()
  test.data <- sub.patient.df
  ref.data <- variant.df[variant.df$variant_type == "SNV", ]
  for (j in unique(ref.data$variant_go_name)) {
    test.data$feat <- ifelse(
      sub.patient.df$de_id %in% ref.data$de_id[ref.data$variant_go_name == j], 0,
      ifelse(
        !(sub.patient.df$DNA_SNV %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    if (sum(na.omit(test.data$feat == 0)) >= 5) {
      var <- append(var, j)
      colnames(test.data)[ncol(test.data)] <- j
    } else {
      test.data <- test.data[, -ncol(test.data)]
    }
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  snv.type <- variant.df$snv_type
  names(snv.type) <- variant.df$variant_go_name
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Single nucleotide variants (N, %)", var),
      Type = c("", snv.type[var]),
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### CNVs

  # create data for testing
  total.patients <- sum(!(patient.df$DNA_CNV %in% c("Fail", "Not Performed")))
  var <- c()
  test.data <- sub.patient.df
  ref.data <- variant.df[variant.df$variant_type == "CNV", ]
  for (j in unique(ref.data$variant_go_name)) {
    test.data$feat <- ifelse(
      sub.patient.df$de_id %in% ref.data$de_id[ref.data$variant_go_name == j], 0,
      ifelse(
        !(sub.patient.df$DNA_CNV %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    if (sum(na.omit(test.data$feat == 0)) >= 5) {
      var <- append(var, j)
      colnames(test.data)[ncol(test.data)] <- j
    } else {
      test.data <- test.data[, -ncol(test.data)]
    }
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Copy number variants (N, %)", var),
      Type = "",
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### Fusions

  # create data for testing
  total.patients <- sum(!(patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")))
  var <- c()
  test.data <- sub.patient.df
  ref.data <- variant.df[variant.df$variant_type == "Fusion", ]
  ref.data$variant_go_name[
    grep("Skip", ref.data$variant_go_name)
  ] <- grep("Skip", ref.data$variant_go_name, value = TRUE)
  for (j in unique(ref.data$variant_go_name)) {
    test.data$feat <- ifelse(
      sub.patient.df$de_id %in% ref.data$de_id[ref.data$variant_go_name == j], 0,
      ifelse(
        !(sub.patient.df$RNA_Rearrangements %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    if (sum(na.omit(test.data$feat == 0)) >= 5) {
      var <- append(var, j)
      colnames(test.data)[ncol(test.data)] <- j
    } else {
      test.data <- test.data[, -ncol(test.data)]
    }
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Fusions/Skipping Variants (N, %)", var),
      Type = "",
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### multiple testing correction

  # adjust p-values for multiple testing
  for (j in grep("P", colnames(results))) {
    if (colnames(results)[j] != "P1") {
      results[!(results[, j] %in%
        c("FDR q-value", "P for trend", "-", "")), j] <- formatC(
        p.adjust(
          as.numeric(results[!(results[, j] %in%
            c("FDR q-value", "P for trend", "-", "")), j]),
          method = "BH"
        ),
        digits = 1, format = "e"
      )
    }
  }

  ### write out results

  # create workbook
  if (i == 1) {
    wb <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb, groups[i])

  writeData(wb, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(33, 12, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = 1,
    rows = c(
      (grep("^Single", results$Variable) + 1):(grep("^Copy", results$Variable) - 1),
      (grep("^Copy", results$Variable) + 1):(grep("^Fusions", results$Variable) - 1),
      (grep("^Fusions", results$Variable) + 1):nrow(results)
    ),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb, groups[i], cols = c(3, 4), rows = 1)
  mergeCells(wb, groups[i], cols = c(5:8), rows = 1)
  mergeCells(wb, groups[i], cols = c(9:12), rows = 1)
  mergeCells(wb, groups[i], cols = c(13:16), rows = 1)
  mergeCells(wb, groups[i], cols = c(17:20), rows = 1)
  mergeCells(wb, groups[i], cols = c(21:24), rows = 1)
  mergeCells(wb, groups[i], cols = c(25:28), rows = 1)

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(
      grep("^Single", results$Variable),
      grep("^Copy", results$Variable),
      grep("^Fusions", results$Variable)
    ),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb, groups[i], FALSE)

  # save workbook and table of results
  saveWorkbook(
    wb, "2_Genomic_alterations/Patient_alteration_prevalence_by_variant.xlsx",
    overwrite = TRUE
  )

  # plot significant results
  plot.data <- data.frame(
    `Age group` = c(
      rep(
        "≥65",
        length((grep("^Single", results$Variable) + 1):nrow(results))
      ),
      rep(
        gsub("age_", "<", age_strat)[1],
        length((grep("^Single", results$Variable) + 1):nrow(results))
      ),
      rep(
        gsub("age_", "<", age_strat)[2],
        length((grep("^Single", results$Variable) + 1):nrow(results))
      ),
      rep(
        gsub("age_", "<", age_strat)[3],
        length((grep("^Single", results$Variable) + 1):nrow(results))
      ),
      rep(
        gsub("age_", "<", age_strat)[4],
        length((grep("^Single", results$Variable) + 1):nrow(results))
      ),
      rep(
        gsub("age_", "<", age_strat)[5],
        length((grep("^Single", results$Variable) + 1):nrow(results))
      )
    ),
    Alteration = "Individual variants",
    Gene = rep(
      results$Variable[
        (grep("^Single", results$Variable) + 1):nrow(results)
      ],
      length(age_strat) + 1
    ),
    Frequency = c(
      as.numeric(sapply(
        strsplit(results$`N1 summary stats`[
          (grep("^Single", results$Variable) + 1):nrow(results)
        ], "\\("), function(x) {
          strsplit(x[2], "%")[[1]][1]
        }
      )),
      as.numeric(sapply(
        strsplit(results$`N2 summary stats`[
          (grep("^Single", results$Variable) + 1):nrow(results)
        ], "\\("), function(x) {
          strsplit(x[2], "%")[[1]][1]
        }
      )),
      as.numeric(sapply(
        strsplit(results$`N3 summary stats`[
          (grep("^Single", results$Variable) + 1):nrow(results)
        ], "\\("), function(x) {
          strsplit(x[2], "%")[[1]][1]
        }
      )),
      as.numeric(sapply(
        strsplit(results$`N4 summary stats`[
          (grep("^Single", results$Variable) + 1):nrow(results)
        ], "\\("), function(x) {
          strsplit(x[2], "%")[[1]][1]
        }
      )),
      as.numeric(sapply(
        strsplit(results$`N5 summary stats`[
          (grep("^Single", results$Variable) + 1):nrow(results)
        ], "\\("), function(x) {
          strsplit(x[2], "%")[[1]][1]
        }
      )),
      as.numeric(sapply(
        strsplit(results$`N6 summary stats`[
          (grep("^Single", results$Variable) + 1):nrow(results)
        ], "\\("), function(x) {
          strsplit(x[2], "%")[[1]][1]
        }
      ))
    ),
    P = rep(
      as.numeric(results$Ptrend[
        (grep("^Single", results$Variable) + 1):nrow(results)
      ]), length(age_strat) + 1
    ),
    check.names = FALSE
  )
  plot.data <- plot.data[plot.data$P <= 0.25 & !is.na(plot.data$P), ]
  plot.data$Gene <- factor(plot.data$Gene, levels = rev(unique(plot.data$Gene)))

  g <- ggplot(data = plot.data, aes(x = Gene, y = Frequency, fill = `Age group`)) +
    geom_bar(stat = "identity", position = "dodge", color = "black") +
    geom_text(
      aes(label = paste(Frequency, "%", sep = "")),
      position = position_dodge(width = 0.9), size = 3, hjust = -0.1
    ) +
    scale_x_discrete(labels = scales::wrap_format(15)) +
    scale_y_continuous(position = "right", limits = c(0, max(plot.data$Frequency) + 10)) +
    scale_fill_manual(
      labels = c(names(table(plot.data$`Age group`))[1:5], expression("" >= 65)),
      values = colorRampPalette(c(labcorp.col[8], labcorp.col[1]))(length(age_strat) + 1)
    ) +
    scale_color_manual(values = rep("black", length(age_strat) + 1)) +
    facet_grid(Alteration ~ ., scale = "free", space = "free") +
    coord_flip() +
    theme_bw() +
    labs(y = "Prevalence (%)", x = "Genomic alteration") +
    guides(fill = guide_legend(override.aes = list(shape = NA), reverse = TRUE)) +
    theme(
      text = element_text(size = 16),
      axis.ticks.x = element_blank(), axis.text.x = element_blank()
    )
  ggsave(
    paste("2_Genomic_alterations/Alteration_associations_variant_", file.names[i], ".pdf", sep = ""),
    g,
    device = "pdf", width = 5, height = length(unique(plot.data$Gene))
  )
}
```

## Immune-related features

### Immunotherapy markers (TMB, PD-L1) and immune gene expression signatures (CP, CTAB, TIGS)

```{r immune-markers-signatures}
# define groups to run analyses and generate plots for and their file names
groups <- c("All patients", "Male", "Female")
file.names <- c("all_patients", "males", "females")

### original run ###

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      N = "All patients", `Summary stats` = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Marker/Signature",
      N = "N", `Summary stats` = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "OR/Beta", P1 = "P",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR/Beta", P2 = "P",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "OR/Beta", P3 = "P",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "OR/Beta", P4 = "P",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "OR/Beta", P5 = "P",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "OR/Beta", P6 = "P",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      N = nrow(sub.patient.df), `Summary stats` = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  ### TMB score (mut/Mb)

  # perform testing
  sub.patient.df$log_TMB <- log(sub.patient.df$TMB + 1)
  var <- "log_TMB"
  ref <- rep("≥65", length(age_strat))
  log.res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.patient.df
  )
  var <- "TMB"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.patient.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "TMB (Mut/Mb) (Mean±SD)",
      N = nrow(sub.patient.df[!is.na(sub.patient.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.patient.df[, var])), 1),
        round(sd(na.omit(sub.patient.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = log.res$beta[[1]],
      P2 = log.res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = log.res$beta[[2]],
      P3 = log.res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = log.res$beta[[3]],
      P4 = log.res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = log.res$beta[[4]],
      P5 = log.res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = log.res$beta[[5]],
      P6 = log.res$p[[5]],
      Ptrend = formatC(log.res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### TMB very high, high, not high

  # create data for testing
  total.patients <- length(sub.patient.df[!is.na(sub.patient.df$TMB_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    `Very high (≥20)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$TMB_interp == "Very high (≥20)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$TMB_interp)], NA, 1
      )
    ),
    `High (10-19)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$TMB_interp == "High (10-19)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$TMB_interp)], NA, 1
      )
    ),
    `Not high (<10)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$TMB_interp == "Not high (<10)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$TMB_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("Very high (≥20)", "High (10-19)", "Not high (<10)")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("TMB level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### PD-L1 score (% expressing cells)

  # perform testing
  var <- "PD_L1_IHC_22C3_result"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.patient.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "PD-L1 22C3 % TPS (Mean±SD)",
      N = nrow(sub.patient.df[!is.na(sub.patient.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.patient.df[, var])), 1),
        round(sd(na.omit(sub.patient.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = res$beta[[1]],
      P2 = res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = res$beta[[2]],
      P3 = res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = res$beta[[3]],
      P4 = res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = res$beta[[4]],
      P5 = res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = res$beta[[5]],
      P6 = res$p[[5]],
      Ptrend = formatC(res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### PD-L1 high, low, negative

  # create data for testing
  total.patients <- length(sub.patient.df[!is.na(sub.patient.df$PD_L1_IHC_22C3_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    `High (≥50%)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$PD_L1_IHC_22C3_interp == "High (≥50%)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$PD_L1_IHC_22C3_interp)], NA, 1
      )
    ),
    `Low (1-49%)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$PD_L1_IHC_22C3_interp == "Low (1-49%)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$PD_L1_IHC_22C3_interp)], NA, 1
      )
    ),
    `Negative (<1%)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$PD_L1_IHC_22C3_interp == "Negative (<1%)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$PD_L1_IHC_22C3_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("High (≥50%)", "Low (1-49%)", "Negative (<1%)")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("PD-L1 level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### TIGS score

  # perform testing
  var <- "TIGS"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.immune.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "TIGS score (Mean±SD)",
      N = nrow(sub.immune.df[!is.na(sub.immune.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.immune.df[, var])), 1),
        round(sd(na.omit(sub.immune.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = res$beta[[1]],
      P2 = res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = res$beta[[2]],
      P3 = res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = res$beta[[3]],
      P4 = res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = res$beta[[4]],
      P5 = res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = res$beta[[5]],
      P6 = res$p[[5]],
      Ptrend = formatC(res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### TIGS group strong, moderate, weak

  # create data for testing
  total.patients <- length(sub.immune.df[!is.na(sub.immune.df$TIGS_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    Strong = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$TIGS_interp == "Strong"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$TIGS_interp)], NA, 1
      )
    ),
    Moderate = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$TIGS_interp == "Moderate"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$TIGS_interp)], NA, 1
      )
    ),
    Weak = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$TIGS_interp == "Weak"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$TIGS_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("Strong", "Moderate", "Weak")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("TIGS score level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### CP score

  # perform testing
  sub.immune.df$log_CP <- log(sub.immune.df$CP + 1)
  var <- "log_CP"
  ref <- rep("≥65", length(age_strat))
  log.res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.immune.df
  )
  var <- "CP"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.immune.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "CP score (Mean±SD)",
      N = nrow(sub.immune.df[!is.na(sub.immune.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.immune.df[, var])), 1),
        round(sd(na.omit(sub.immune.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = log.res$beta[[1]],
      P2 = log.res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = log.res$beta[[2]],
      P3 = log.res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = log.res$beta[[3]],
      P4 = log.res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = log.res$beta[[4]],
      P5 = log.res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = log.res$beta[[5]],
      P6 = log.res$p[[5]],
      Ptrend = formatC(log.res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### CP group high, moderate, poor

  # create data for testing
  total.patients <- length(sub.immune.df[!is.na(sub.immune.df$CP_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    High = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CP_interp == "High"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CP_interp)], NA, 1
      )
    ),
    Moderate = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CP_interp == "Moderate"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CP_interp)], NA, 1
      )
    ),
    Poor = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CP_interp == "Poor"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CP_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("High", "Moderate", "Poor")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("CP score level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### CTAB score

  # perform testing
  sub.immune.df$log_CTAB <- log(sub.immune.df$CTAB + 1)
  var <- "log_CTAB"
  ref <- rep("≥65", length(age_strat))
  log.res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.immune.df
  )
  var <- "CTAB"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
    data.df = sub.immune.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "CTAB score (Mean±SD)",
      N = nrow(sub.immune.df[!is.na(sub.immune.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.immune.df[, var])), 1),
        round(sd(na.omit(sub.immune.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = log.res$beta[[1]],
      P2 = log.res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = log.res$beta[[2]],
      P3 = log.res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = log.res$beta[[3]],
      P4 = log.res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = log.res$beta[[4]],
      P5 = log.res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = log.res$beta[[5]],
      P6 = log.res$p[[5]],
      Ptrend = formatC(log.res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### CTAB group high, low

  # create data for testing
  total.patients <- length(sub.immune.df[!is.na(sub.immune.df$CTAB_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    High = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CTAB_interp == "High"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CTAB_interp)], NA, 1
      )
    ),
    Low = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CTAB_interp == "Low"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CTAB_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("High", "Low")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("CTAB score level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### write out results

  # create workbook
  if (i == 1) {
    wb <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb, groups[i])

  writeData(wb, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(32, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = 1,
    rows = c(
      which(results$Variable == "Very high (≥20)"):which(results$Variable == "Not high (<10)"),
      which(results$Variable == "High (≥50%)"):which(results$Variable == "Negative (<1%)"),
      which(results$Variable == "Strong"):which(results$Variable == "Weak"),
      which(results$Variable == "High")[1]:which(results$Variable == "Poor"),
      which(results$Variable == "High")[2]:which(results$Variable == "Low")
    ),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb, groups[i], cols = c(2, 3), rows = 1)
  mergeCells(wb, groups[i], cols = c(4:7), rows = 1)
  mergeCells(wb, groups[i], cols = c(8:11), rows = 1)
  mergeCells(wb, groups[i], cols = c(12:15), rows = 1)
  mergeCells(wb, groups[i], cols = c(16:19), rows = 1)
  mergeCells(wb, groups[i], cols = c(20:23), rows = 1)
  mergeCells(wb, groups[i], cols = c(24:27), rows = 1)

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(
      grep("TMB", results$Variable),
      grep("PD-L1", results$Variable),
      grep("TIGS", results$Variable),
      grep("CP", results$Variable),
      grep("CTAB", results$Variable)
    ),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb, groups[i], FALSE)

  # save workbook and table of results
  saveWorkbook(
    wb, "3_Immune_related_features/Immune_marker_signature_associations.xlsx",
    overwrite = TRUE
  )

  # plot distributions of significant markers/signatures per age group
  plot.data <- data.frame(
    de_id = rep(sub.patient.df$de_id, 5),
    `Age group` = c(
      sub.patient.df$age_45, sub.patient.df$age_50,
      sub.patient.df$age_55, sub.patient.df$age_60, sub.patient.df$age_65
    ),
    TMB = rep(sub.patient.df$TMB, 5),
    TIGS = rep(sub.immune.df$TIGS, 5),
    CP = rep(sub.immune.df$CP, 5),
    CTAB = rep(sub.immune.df$CTAB, 5),
    check.names = FALSE
  )
  plot.data <- unique(plot.data[!is.na(plot.data$`Age group`), ])
  pvals <- data.frame(
    `Age group 1` = rep("≥65", 5),
    `Age group 2` = gsub("age_", "<", age_strat),
    TMB_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    TIGS_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    CP_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    CTAB_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    check.names = FALSE
  )
  plot.data$`Age group` <- factor(plot.data$`Age group`, levels = rev(names(table(plot.data$`Age group`))))
  if (sum(grepl("\\*", pvals$TMB_labels)) > 0) {
    g1 <- ggplot(
      plot.data[!is.na(plot.data$TMB), ], aes(y = TMB, x = `Age group`)
    ) +
      geom_hline(yintercept = 10, color = "grey50", linetype = "dashed") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$TMB_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$TMB_labels != "ns", ]), 1) * 12,
            function(x) {
              x + max(na.omit(plot.data$TMB))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = TMB_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 25, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 0, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TMB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -10, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TMB)) + (nrow(pvals[pvals$TMB_labels != "ns", ]) * 12))
      ) +
      theme_classic() +
      labs(y = "TMB (Mut/Mb)", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g1 <- ggplot(
      plot.data[!is.na(plot.data$TMB), ], aes(y = TMB, x = `Age group`)
    ) +
      geom_hline(yintercept = 10, color = "grey50", linetype = "dashed") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 25, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 0, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TMB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -10, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TMB)) + (nrow(pvals[pvals$TMB_labels != "ns", ]) * 12))
      ) +
      theme_classic() +
      labs(y = "TMB (Mut/Mb)", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  }
  if (sum(grepl("\\*", pvals$TIGS_labels)) > 0) {
    g2 <- ggplot(
      plot.data[!is.na(plot.data$TIGS), ], aes(y = TIGS, x = `Age group`)
    ) +
      geom_hline(yintercept = 62, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 43.72, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$TIGS_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$TIGS_labels != "ns", ]), 1) * 8,
            function(x) {
              x + max(na.omit(plot.data$TIGS))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = TIGS_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "Strong", x = 0, y = 70, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 50, color = "black", size = 6) +
      annotate("text", label = "Weak", x = 0, y = 35, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TIGS)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -5, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TIGS)) + (nrow(pvals[pvals$TIGS_labels != "ns", ]) * 8))
      ) +
      theme_classic() +
      labs(y = "TIGS score", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g2 <- ggplot(
      plot.data[!is.na(plot.data$TIGS), ], aes(y = TIGS, x = `Age group`)
    ) +
      geom_hline(yintercept = 62, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 43.72, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "Strong", x = 0, y = 70, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 50, color = "black", size = 6) +
      annotate("text", label = "Weak", x = 0, y = 35, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TIGS)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -5, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TIGS)) + (nrow(pvals[pvals$TIGS_labels != "ns", ]) * 8))
      ) +
      theme_classic() +
      labs(y = "TIGS score", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  }
  if (sum(grepl("\\*", pvals$CP_labels)) > 0) {
    g3 <- ggplot(
      plot.data[!is.na(plot.data$CP), ], aes(y = CP, x = `Age group`)
    ) +
      geom_hline(yintercept = 66, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 33, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$CP_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$CP_labels != "ns", ]), 1) * 8,
            function(x) {
              x + max(na.omit(plot.data$CP))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = CP_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 74, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 42, color = "black", size = 6) +
      annotate("text", label = "Poor", x = 0, y = 25, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CP)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -7, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$CP)) + (nrow(pvals[pvals$CP_labels != "ns", ]) * 8))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CP score") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g3 <- ggplot(
      plot.data[!is.na(plot.data$CP), ], aes(y = CP, x = `Age group`)
    ) +
      geom_hline(yintercept = 66, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 33, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 74, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 42, color = "black", size = 6) +
      annotate("text", label = "Poor", x = 0, y = 25, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CP)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -7, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$CP)) + (nrow(pvals[pvals$CP_labels != "ns", ]) * 8))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CP score") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  }
  if (sum(grepl("\\*", pvals$CTAB_labels)) > 0) {
    g4 <- ggplot(
      plot.data[!is.na(plot.data$CTAB), ], aes(y = CTAB, x = `Age group`)
    ) +
      geom_hline(yintercept = 171, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$CTAB_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$CTAB_labels != "ns", ]), 1) * 90,
            function(x) {
              x + max(na.omit(plot.data$CTAB))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = CTAB_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 250, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 100, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CTAB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -70, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-70, max(na.omit(plot.data$CTAB)) + (nrow(pvals[pvals$CTAB_labels != "ns", ]) * 90))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CTAB score") +
      theme(
        text = element_text(size = 24),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g4 <- ggplot(
      plot.data[!is.na(plot.data$CTAB), ], aes(y = CTAB, x = `Age group`)
    ) +
      geom_hline(yintercept = 171, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 250, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 100, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CTAB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -70, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-70, max(na.omit(plot.data$CTAB)) + (nrow(pvals[pvals$CTAB_labels != "ns", ]) * 90))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CTAB score") +
      theme(
        text = element_text(size = 24),
        axis.title.y = element_text(vjust = 1)
      )
  }

  g <- ggarrange(
    g1, NULL, g2, NULL, g3, NULL, g4,
    nrow = 7, ncol = 1, heights = c(1, 0, 1, 0, 1, 0, 1.2), align = "v"
  )
  ggsave(
    paste(
      "3_Immune_related_features/Immune_marker_signature_associations_",
      file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 10, height = 15, limitsize = FALSE
  )
}

### adjusting for ALK/EGFR positivity ###

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      N = "All patients", `Summary stats` = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Marker/Signature",
      N = "N", `Summary stats` = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "OR/Beta", P1 = "P",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR/Beta", P2 = "P",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "OR/Beta", P3 = "P",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "OR/Beta", P4 = "P",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "OR/Beta", P5 = "P",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "OR/Beta", P6 = "P",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      N = nrow(sub.patient.df), `Summary stats` = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  ### TMB score (mut/Mb)

  # perform testing
  sub.patient.df$log_TMB <- log(sub.patient.df$TMB + 1)
  var <- "log_TMB"
  ref <- rep("≥65", length(age_strat))
  log.res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.patient.df
  )
  var <- "TMB"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.patient.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "TMB (Mut/Mb) (Mean±SD)",
      N = nrow(sub.patient.df[!is.na(sub.patient.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.patient.df[, var])), 1),
        round(sd(na.omit(sub.patient.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = log.res$beta[[1]],
      P2 = log.res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = log.res$beta[[2]],
      P3 = log.res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = log.res$beta[[3]],
      P4 = log.res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = log.res$beta[[4]],
      P5 = log.res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = log.res$beta[[5]],
      P6 = log.res$p[[5]],
      Ptrend = formatC(log.res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### TMB very high, high, not high

  # create data for testing
  total.patients <- length(sub.patient.df[!is.na(sub.patient.df$TMB_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    `Very high (≥20)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$TMB_interp == "Very high (≥20)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$TMB_interp)], NA, 1
      )
    ),
    `High (10-19)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$TMB_interp == "High (10-19)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$TMB_interp)], NA, 1
      )
    ),
    `Not high (<10)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$TMB_interp == "Not high (<10)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$TMB_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("Very high (≥20)", "High (10-19)", "Not high (<10)")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("TMB level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### PD-L1 score (% expressing cells)

  # perform testing
  var <- "PD_L1_IHC_22C3_result"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.patient.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "PD-L1 22C3 % TPS (Mean±SD)",
      N = nrow(sub.patient.df[!is.na(sub.patient.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.patient.df[, var])), 1),
        round(sd(na.omit(sub.patient.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = res$beta[[1]],
      P2 = res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = res$beta[[2]],
      P3 = res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = res$beta[[3]],
      P4 = res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = res$beta[[4]],
      P5 = res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = res$beta[[5]],
      P6 = res$p[[5]],
      Ptrend = formatC(res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### PD-L1 high, low, negative

  # create data for testing
  total.patients <- length(sub.patient.df[!is.na(sub.patient.df$PD_L1_IHC_22C3_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    `High (≥50%)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$PD_L1_IHC_22C3_interp == "High (≥50%)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$PD_L1_IHC_22C3_interp)], NA, 1
      )
    ),
    `Low (1-49%)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$PD_L1_IHC_22C3_interp == "Low (1-49%)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$PD_L1_IHC_22C3_interp)], NA, 1
      )
    ),
    `Negative (<1%)` = ifelse(
      sub.patient.df$de_id %in%
        sub.patient.df$de_id[sub.patient.df$PD_L1_IHC_22C3_interp == "Negative (<1%)"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.patient.df$de_id) |
          sub.patient.df$de_id %in%
            sub.patient.df$de_id[is.na(sub.patient.df$PD_L1_IHC_22C3_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("High (≥50%)", "Low (1-49%)", "Negative (<1%)")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("PD-L1 level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### TIGS score

  # perform testing
  var <- "TIGS"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.immune.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "TIGS score (Mean±SD)",
      N = nrow(sub.immune.df[!is.na(sub.immune.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.immune.df[, var])), 1),
        round(sd(na.omit(sub.immune.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = res$beta[[1]],
      P2 = res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = res$beta[[2]],
      P3 = res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = res$beta[[3]],
      P4 = res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = res$beta[[4]],
      P5 = res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = res$beta[[5]],
      P6 = res$p[[5]],
      Ptrend = formatC(res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### TIGS group strong, moderate, weak

  # create data for testing
  total.patients <- length(sub.immune.df[!is.na(sub.immune.df$TIGS_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    Strong = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$TIGS_interp == "Strong"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$TIGS_interp)], NA, 1
      )
    ),
    Moderate = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$TIGS_interp == "Moderate"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$TIGS_interp)], NA, 1
      )
    ),
    Weak = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$TIGS_interp == "Weak"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$TIGS_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("Strong", "Moderate", "Weak")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("TIGS score level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### CP score

  # perform testing
  sub.immune.df$log_CP <- log(sub.immune.df$CP + 1)
  var <- "log_CP"
  ref <- rep("≥65", length(age_strat))
  log.res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.immune.df
  )
  var <- "CP"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.immune.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "CP score (Mean±SD)",
      N = nrow(sub.immune.df[!is.na(sub.immune.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.immune.df[, var])), 1),
        round(sd(na.omit(sub.immune.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = log.res$beta[[1]],
      P2 = log.res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = log.res$beta[[2]],
      P3 = log.res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = log.res$beta[[3]],
      P4 = log.res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = log.res$beta[[4]],
      P5 = log.res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = log.res$beta[[5]],
      P6 = log.res$p[[5]],
      Ptrend = formatC(log.res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### CP group high, moderate, poor

  # create data for testing
  total.patients <- length(sub.immune.df[!is.na(sub.immune.df$CP_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    High = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CP_interp == "High"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CP_interp)], NA, 1
      )
    ),
    Moderate = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CP_interp == "Moderate"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CP_interp)], NA, 1
      )
    ),
    Poor = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CP_interp == "Poor"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CP_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("High", "Moderate", "Poor")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("CP score level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### CTAB score

  # perform testing
  sub.immune.df$log_CTAB <- log(sub.immune.df$CTAB + 1)
  var <- "log_CTAB"
  ref <- rep("≥65", length(age_strat))
  log.res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.immune.df
  )
  var <- "CTAB"
  ref <- rep("≥65", length(age_strat))
  res <- quantStratTest(
    var = var, strata = age_strat, ref = ref,
    covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
    data.df = sub.immune.df
  )

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = "CTAB score (Mean±SD)",
      N = nrow(sub.immune.df[!is.na(sub.immune.df[, var]), ]),
      `Summary stats` = paste(
        round(mean(na.omit(sub.immune.df[, var])), 1),
        round(sd(na.omit(sub.immune.df[, var])), 1),
        sep = "±"
      ),
      N1 = res$n[[1]][2],
      `N1 summary stats` = res$stats[[1]][2],
      OR1 = "Ref",
      P1 = "Ref",
      N2 = res$n[[1]][1],
      `N2 summary stats` = res$stats[[1]][1],
      OR2 = log.res$beta[[1]],
      P2 = log.res$p[[1]],
      N3 = res$n[[2]][1],
      `N3 summary stats` = res$stats[[2]][1],
      OR3 = log.res$beta[[2]],
      P3 = log.res$p[[2]],
      N4 = res$n[[3]][1],
      `N4 summary stats` = res$stats[[3]][1],
      OR4 = log.res$beta[[3]],
      P4 = log.res$p[[3]],
      N5 = res$n[[4]][1],
      `N5 summary stats` = res$stats[[4]][1],
      OR5 = log.res$beta[[4]],
      P5 = log.res$p[[4]],
      N6 = res$n[[5]][1],
      `N6 summary stats` = res$stats[[5]][1],
      OR6 = log.res$beta[[5]],
      P6 = log.res$p[[5]],
      Ptrend = formatC(log.res$ptrend, digits = 1, format = "e"),
      check.names = FALSE
    )
  )

  ### CTAB group high, low

  # create data for testing
  total.patients <- length(sub.immune.df[!is.na(sub.immune.df$CTAB_interp), "de_id"])
  test.data <- data.frame(
    sub.patient.df,
    High = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CTAB_interp == "High"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CTAB_interp)], NA, 1
      )
    ),
    Low = ifelse(
      sub.patient.df$de_id %in% sub.immune.df$de_id[sub.immune.df$CTAB_interp == "Low"], 0,
      ifelse(
        !(sub.patient.df$de_id %in% sub.immune.df$de_id) |
          sub.patient.df$de_id %in% sub.immune.df$de_id[is.na(sub.immune.df$CTAB_interp)], NA, 1
      )
    ),
    check.names = FALSE
  )

  # perform testing
  var <- c("High", "Low")
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("CTAB score level (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(
            colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
              total.patients * 100, 1
          ), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### write out results

  # create workbook
  if (i == 1) {
    wb2 <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb2, groups[i])

  writeData(wb2, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb2, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(32, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb2, groups[i],
    cols = 1,
    rows = c(
      which(results$Variable == "Very high (≥20)"):which(results$Variable == "Not high (<10)"),
      which(results$Variable == "High (≥50%)"):which(results$Variable == "Negative (<1%)"),
      which(results$Variable == "Strong"):which(results$Variable == "Weak"),
      which(results$Variable == "High")[1]:which(results$Variable == "Poor"),
      which(results$Variable == "High")[2]:which(results$Variable == "Low")
    ),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb2, groups[i], cols = c(2, 3), rows = 1)
  mergeCells(wb2, groups[i], cols = c(4:7), rows = 1)
  mergeCells(wb2, groups[i], cols = c(8:11), rows = 1)
  mergeCells(wb2, groups[i], cols = c(12:15), rows = 1)
  mergeCells(wb2, groups[i], cols = c(16:19), rows = 1)
  mergeCells(wb2, groups[i], cols = c(20:23), rows = 1)
  mergeCells(wb2, groups[i], cols = c(24:27), rows = 1)

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(
      grep("TMB", results$Variable),
      grep("PD-L1", results$Variable),
      grep("TIGS", results$Variable),
      grep("CP", results$Variable),
      grep("CTAB", results$Variable)
    ),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb2, groups[i], FALSE)

  # save workbook and table of results
  saveWorkbook(
    wb2, "3_Immune_related_features/ALK_EGFR_adjusted/Immune_marker_signature_associations_ALK_EGFR_adj.xlsx",
    overwrite = TRUE
  )

  # plot distributions of significant markers/signatures per age group
  plot.data <- data.frame(
    de_id = rep(sub.patient.df$de_id, 5),
    `Age group` = c(
      sub.patient.df$age_45, sub.patient.df$age_50,
      sub.patient.df$age_55, sub.patient.df$age_60, sub.patient.df$age_65
    ),
    TMB = rep(sub.patient.df$TMB, 5),
    TIGS = rep(sub.immune.df$TIGS, 5),
    CP = rep(sub.immune.df$CP, 5),
    CTAB = rep(sub.immune.df$CTAB, 5),
    check.names = FALSE
  )
  plot.data <- unique(plot.data[!is.na(plot.data$`Age group`), ])
  pvals <- data.frame(
    `Age group 1` = rep("≥65", 5),
    `Age group 2` = gsub("age_", "<", age_strat),
    TMB_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    TIGS_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    CP_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    CTAB_labels = sapply(
      paste("P", 2:6, sep = ""),
      function(x) {
        ifelse(
          as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.0001, "****",
          ifelse(
            as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.001, "***",
            ifelse(
              as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.01, "**",
              ifelse(
                as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), x]) < 0.05, "*", "ns"
              )
            )
          )
        )
      }
    ),
    check.names = FALSE
  )
  plot.data$`Age group` <- factor(plot.data$`Age group`, levels = rev(names(table(plot.data$`Age group`))))
  if (sum(grepl("\\*", pvals$TMB_labels)) > 0) {
    g1 <- ggplot(
      plot.data[!is.na(plot.data$TMB), ], aes(y = TMB, x = `Age group`)
    ) +
      geom_hline(yintercept = 10, color = "grey50", linetype = "dashed") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$TMB_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$TMB_labels != "ns", ]), 1) * 12,
            function(x) {
              x + max(na.omit(plot.data$TMB))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = TMB_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 25, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 0, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TMB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -10, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TMB)) + (nrow(pvals[pvals$TMB_labels != "ns", ]) * 12))
      ) +
      theme_classic() +
      labs(y = "TMB (Mut/Mb)", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g1 <- ggplot(
      plot.data[!is.na(plot.data$TMB), ], aes(y = TMB, x = `Age group`)
    ) +
      geom_hline(yintercept = 10, color = "grey50", linetype = "dashed") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 25, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 0, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TMB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -10, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TMB)) + (nrow(pvals[pvals$TMB_labels != "ns", ]) * 12))
      ) +
      theme_classic() +
      labs(y = "TMB (Mut/Mb)", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  }
  if (sum(grepl("\\*", pvals$TIGS_labels)) > 0) {
    g2 <- ggplot(
      plot.data[!is.na(plot.data$TIGS), ], aes(y = TIGS, x = `Age group`)
    ) +
      geom_hline(yintercept = 62, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 43.72, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$TIGS_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$TIGS_labels != "ns", ]), 1) * 8,
            function(x) {
              x + max(na.omit(plot.data$TIGS))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = TIGS_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "Strong", x = 0, y = 70, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 50, color = "black", size = 6) +
      annotate("text", label = "Weak", x = 0, y = 35, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TIGS)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -5, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TIGS)) + (nrow(pvals[pvals$TIGS_labels != "ns", ]) * 8))
      ) +
      theme_classic() +
      labs(y = "TIGS score", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g2 <- ggplot(
      plot.data[!is.na(plot.data$TIGS), ], aes(y = TIGS, x = `Age group`)
    ) +
      geom_hline(yintercept = 62, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 43.72, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "Strong", x = 0, y = 70, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 50, color = "black", size = 6) +
      annotate("text", label = "Weak", x = 0, y = 35, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$TIGS)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -5, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$TIGS)) + (nrow(pvals[pvals$TIGS_labels != "ns", ]) * 8))
      ) +
      theme_classic() +
      labs(y = "TIGS score", x = "") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  }
  if (sum(grepl("\\*", pvals$CP_labels)) > 0) {
    g3 <- ggplot(
      plot.data[!is.na(plot.data$CP), ], aes(y = CP, x = `Age group`)
    ) +
      geom_hline(yintercept = 66, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 33, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$CP_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$CP_labels != "ns", ]), 1) * 8,
            function(x) {
              x + max(na.omit(plot.data$CP))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = CP_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 74, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 42, color = "black", size = 6) +
      annotate("text", label = "Poor", x = 0, y = 25, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CP)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -7, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$CP)) + (nrow(pvals[pvals$CP_labels != "ns", ]) * 8))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CP score") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g3 <- ggplot(
      plot.data[!is.na(plot.data$CP), ], aes(y = CP, x = `Age group`)
    ) +
      geom_hline(yintercept = 66, linetype = "dashed", color = "grey50") +
      geom_hline(yintercept = 33, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 74, color = "black", size = 6) +
      annotate("text", label = "Moderate", x = 0, y = 42, color = "black", size = 6) +
      annotate("text", label = "Poor", x = 0, y = 25, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CP)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -7, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-10, max(na.omit(plot.data$CP)) + (nrow(pvals[pvals$CP_labels != "ns", ]) * 8))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CP score") +
      theme(
        text = element_text(size = 24),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_text(vjust = 1)
      )
  }
  if (sum(grepl("\\*", pvals$CTAB_labels)) > 0) {
    g4 <- ggplot(
      plot.data[!is.na(plot.data$CTAB), ], aes(y = CTAB, x = `Age group`)
    ) +
      geom_hline(yintercept = 171, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      geom_signif(
        data = data.frame(
          pvals[pvals$CTAB_labels != "ns", ],
          y = sapply(
            seq(1, nrow(pvals[pvals$CTAB_labels != "ns", ]), 1) * 90,
            function(x) {
              x + max(na.omit(plot.data$CTAB))
            }
          ),
          check.names = FALSE
        ),
        aes(xmin = `Age group 1`, xmax = `Age group 2`, y_position = y, annotations = CTAB_labels),
        manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
        color = "black"
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 250, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 100, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CTAB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -70, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-70, max(na.omit(plot.data$CTAB)) + (nrow(pvals[pvals$CTAB_labels != "ns", ]) * 90))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CTAB score") +
      theme(
        text = element_text(size = 24),
        axis.title.y = element_text(vjust = 1)
      )
  } else {
    g4 <- ggplot(
      plot.data[!is.na(plot.data$CTAB), ], aes(y = CTAB, x = `Age group`)
    ) +
      geom_hline(yintercept = 171, linetype = "dashed", color = "grey50") +
      geom_violin(scale = "width", fill = "grey", color = "grey") +
      geom_boxplot(
        width = 0.6, fill = "white", color = "black",
        outlier.size = 3, outlier.alpha = 0.5
      ) +
      stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
      annotate("text", label = "High", x = 0, y = 250, color = "black", size = 6) +
      annotate("text", label = "Low", x = 0, y = 100, color = "black", size = 6) +
      annotate(
        "text",
        label = paste("N=", table(plot.data$`Age group`[!is.na(plot.data$CTAB)]), sep = ""),
        x = c(1, 2, 3, 4, 5, 6), y = -70, color = "black", size = 6
      ) +
      coord_cartesian(
        xlim = c(0, 6),
        ylim = c(-70, max(na.omit(plot.data$CTAB)) + (nrow(pvals[pvals$CTAB_labels != "ns", ]) * 90))
      ) +
      scale_x_discrete(labels = c(
        expression("" >= 65),
        names(table(plot.data$`Age group`))[2:6]
      )) +
      theme_classic() +
      labs(y = "CTAB score") +
      theme(
        text = element_text(size = 24),
        axis.title.y = element_text(vjust = 1)
      )
  }

  g <- ggarrange(
    g1, NULL, g2, NULL, g3, NULL, g4,
    nrow = 7, ncol = 1, heights = c(1, 0, 1, 0, 1, 0, 1.2), align = "v"
  )
  ggsave(
    paste(
      "3_Immune_related_features/ALK_EGFR_adjusted/Immune_marker_signature_associations_ALK_EGFR_adj_",
      file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 10, height = 15, limitsize = FALSE
  )
}

### re-run analysis and plotting for testing males vs females ###

# create result data.frame
results <- data.frame()
results <- rbind(
  results,
  data.frame(
    Variable = "",
    N = "All patients", `Summary stats` = "",
    N1 = "Males", `N1 summary stats` = "",
    N2 = "Females", `N2 summary stats` = "", OR2 = "", P2 = "",
    check.names = FALSE
  )
)
results <- rbind(
  results,
  data.frame(
    Variable = "Marker/Signature",
    N = "N", `Summary stats` = "Summary stats",
    N1 = "N", `N1 summary stats` = "Summary stats",
    N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR/Beta", P2 = "P",
    check.names = FALSE
  )
)

# get total number of patients
results <- rbind(
  results,
  data.frame(
    Variable = "Total number of patients",
    N = nrow(patient.df), `Summary stats` = "-",
    N1 = table(patient.df$patient_sex)[2], `N1 summary stats` = "-",
    N2 = table(patient.df$patient_sex)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
    check.names = FALSE
  )
)

### TMB score (mut/Mb)

# perform testing
patient.df$log_TMB <- log(patient.df$TMB + 1)
var <- "log_TMB"
ref <- c(2, 2)
log.res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = patient.df
)
var <- "TMB"
ref <- c(2, 2)
res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = patient.df
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "TMB (Mut/Mb) (Mean±SD)",
    N = nrow(patient.df[!is.na(patient.df[, var]), ]),
    `Summary stats` = paste(
      round(mean(na.omit(patient.df[, var])), 1),
      round(sd(na.omit(patient.df[, var])), 1),
      sep = "±"
    ),
    N1 = res$n[[1]][1],
    `N1 summary stats` = res$stats[[1]][1],
    N2 = res$n[[2]][1],
    `N2 summary stats` = res$stats[[2]][1],
    OR2 = log.res$beta[[2]],
    P2 = log.res$p[[2]],
    check.names = FALSE
  )
)

### TMB very high, high, not high

# create data for testing
total.patients <- length(patient.df[!is.na(patient.df$TMB_interp), "de_id"])
test.data <- data.frame(
  patient.df,
  `Very high (≥20)` = ifelse(
    patient.df$de_id %in%
      patient.df$de_id[patient.df$TMB_interp == "Very high (≥20)"], 0,
    ifelse(
      !(patient.df$de_id %in% patient.df$de_id) |
        patient.df$de_id %in%
          patient.df$de_id[is.na(patient.df$TMB_interp)], NA, 1
    )
  ),
  `High (10-19)` = ifelse(
    patient.df$de_id %in%
      patient.df$de_id[patient.df$TMB_interp == "High (10-19)"], 0,
    ifelse(
      !(patient.df$de_id %in% patient.df$de_id) |
        patient.df$de_id %in%
          patient.df$de_id[is.na(patient.df$TMB_interp)], NA, 1
    )
  ),
  `Not high (<10)` = ifelse(
    patient.df$de_id %in%
      patient.df$de_id[patient.df$TMB_interp == "Not high (<10)"], 0,
    ifelse(
      !(patient.df$de_id %in% patient.df$de_id) |
        patient.df$de_id %in%
          patient.df$de_id[is.na(patient.df$TMB_interp)], NA, 1
    )
  ),
  check.names = FALSE
)

# perform testing
var <- c("Very high (≥20)", "High (10-19)", "Not high (<10)")
ref <- c(2, 2)
res <- list()
for (j in var) {
  res[[j]] <- catStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("TMB level (N, %)", var),
    N = c(total.patients, rep("", length(var))),
    `Summary stats` = c(
      "",
      paste(
        colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
        round(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
            total.patients * 100, 1
        ), "%", ")",
        sep = ""
      )
    ),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][1]
    })),
    N2 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]][1]
    })),
    OR2 = c("", sapply(res, function(x) {
      x$or[[2]][[1]][1]
    })),
    P2 = c("", sapply(res, function(x) {
      x$p[[2]][[1]][1]
    })),
    check.names = FALSE
  )
)

### PD-L1 score (% expressing cells)

# perform testing
var <- "PD_L1_IHC_22C3_result"
ref <- c(2, 2)
res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = patient.df
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "PD-L1 22C3 % TPS (Mean±SD)",
    N = nrow(patient.df[!is.na(patient.df[, var]), ]),
    `Summary stats` = paste(
      round(mean(na.omit(patient.df[, var])), 1),
      round(sd(na.omit(patient.df[, var])), 1),
      sep = "±"
    ),
    N1 = res$n[[1]][1],
    `N1 summary stats` = res$stats[[1]][1],
    N2 = res$n[[2]][1],
    `N2 summary stats` = res$stats[[2]][1],
    OR2 = res$beta[[2]],
    P2 = res$p[[2]],
    check.names = FALSE
  )
)

### PD-L1 high, low, negative

# create data for testing
total.patients <- length(patient.df[!is.na(patient.df$PD_L1_IHC_22C3_interp), "de_id"])
test.data <- data.frame(
  patient.df,
  `High (≥50%)` = ifelse(
    patient.df$de_id %in%
      patient.df$de_id[patient.df$PD_L1_IHC_22C3_interp == "High (≥50%)"], 0,
    ifelse(
      !(patient.df$de_id %in% patient.df$de_id) |
        patient.df$de_id %in%
          patient.df$de_id[is.na(patient.df$PD_L1_IHC_22C3_interp)], NA, 1
    )
  ),
  `Low (1-49%)` = ifelse(
    patient.df$de_id %in%
      patient.df$de_id[patient.df$PD_L1_IHC_22C3_interp == "Low (1-49%)"], 0,
    ifelse(
      !(patient.df$de_id %in% patient.df$de_id) |
        patient.df$de_id %in%
          patient.df$de_id[is.na(patient.df$PD_L1_IHC_22C3_interp)], NA, 1
    )
  ),
  `Negative (<1%)` = ifelse(
    patient.df$de_id %in%
      patient.df$de_id[patient.df$PD_L1_IHC_22C3_interp == "Negative (<1%)"], 0,
    ifelse(
      !(patient.df$de_id %in% patient.df$de_id) |
        patient.df$de_id %in%
          patient.df$de_id[is.na(patient.df$PD_L1_IHC_22C3_interp)], NA, 1
    )
  ),
  check.names = FALSE
)

# perform testing
var <- c("High (≥50%)", "Low (1-49%)", "Negative (<1%)")
ref <- c(2, 2)
res <- list()
for (j in var) {
  res[[j]] <- catStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("PD-L1 level (N, %)", var),
    N = c(total.patients, rep("", length(var))),
    `Summary stats` = c(
      "",
      paste(
        colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
        round(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
            total.patients * 100, 1
        ), "%", ")",
        sep = ""
      )
    ),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][1]
    })),
    N2 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]][1]
    })),
    OR2 = c("", sapply(res, function(x) {
      x$or[[2]][[1]][1]
    })),
    P2 = c("", sapply(res, function(x) {
      x$p[[2]][[1]][1]
    })),
    check.names = FALSE
  )
)

### TIGS score

# perform testing
var <- "TIGS"
ref <- c(2, 2)
res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = immune.df
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "TIGS score (Mean±SD)",
    N = nrow(immune.df[!is.na(immune.df[, var]), ]),
    `Summary stats` = paste(
      round(mean(na.omit(immune.df[, var])), 1),
      round(sd(na.omit(immune.df[, var])), 1),
      sep = "±"
    ),
    N1 = res$n[[1]][1],
    `N1 summary stats` = res$stats[[1]][1],
    N2 = res$n[[2]][1],
    `N2 summary stats` = res$stats[[2]][1],
    OR2 = res$beta[[2]],
    P2 = res$p[[2]],
    check.names = FALSE
  )
)

### TIGS group strong, moderate, weak

# create data for testing
total.patients <- length(immune.df[!is.na(immune.df$TIGS_interp), "de_id"])
test.data <- data.frame(
  patient.df,
  Strong = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$TIGS_interp == "Strong"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$TIGS_interp)], NA, 1
    )
  ),
  Moderate = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$TIGS_interp == "Moderate"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$TIGS_interp)], NA, 1
    )
  ),
  Weak = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$TIGS_interp == "Weak"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$TIGS_interp)], NA, 1
    )
  ),
  check.names = FALSE
)

# perform testing
var <- c("Strong", "Moderate", "Weak")
ref <- c(2, 2)
res <- list()
for (j in var) {
  res[[j]] <- catStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("TIGS score level (N, %)", var),
    N = c(total.patients, rep("", length(var))),
    `Summary stats` = c(
      "",
      paste(
        colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
        round(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
            total.patients * 100, 1
        ), "%", ")",
        sep = ""
      )
    ),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][1]
    })),
    N2 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]][1]
    })),
    OR2 = c("", sapply(res, function(x) {
      x$or[[2]][[1]][1]
    })),
    P2 = c("", sapply(res, function(x) {
      x$p[[2]][[1]][1]
    })),
    check.names = FALSE
  )
)

### CP score

# perform testing
immune.df$log_CP <- log(immune.df$CP + 1)
var <- "log_CP"
ref <- c(2, 2)
log.res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = immune.df
)
var <- "CP"
ref <- c(2, 2)
res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = immune.df
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "CP score (Mean±SD)",
    N = nrow(immune.df[!is.na(immune.df[, var]), ]),
    `Summary stats` = paste(
      round(mean(na.omit(immune.df[, var])), 1),
      round(sd(na.omit(immune.df[, var])), 1),
      sep = "±"
    ),
    N1 = res$n[[1]][1],
    `N1 summary stats` = res$stats[[1]][1],
    N2 = res$n[[2]][1],
    `N2 summary stats` = res$stats[[2]][1],
    OR2 = log.res$beta[[2]],
    P2 = log.res$p[[2]],
    check.names = FALSE
  )
)

### CP group high, moderate, poor

# create data for testing
total.patients <- length(immune.df[!is.na(immune.df$CP_interp), "de_id"])
test.data <- data.frame(
  patient.df,
  High = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$CP_interp == "High"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$CP_interp)], NA, 1
    )
  ),
  Moderate = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$CP_interp == "Moderate"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$CP_interp)], NA, 1
    )
  ),
  Poor = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$CP_interp == "Poor"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$CP_interp)], NA, 1
    )
  ),
  check.names = FALSE
)

# perform testing
var <- c("High", "Moderate", "Poor")
ref <- c(2, 2)
res <- list()
for (j in var) {
  res[[j]] <- catStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("CP score level (N, %)", var),
    N = c(total.patients, rep("", length(var))),
    `Summary stats` = c(
      "",
      paste(
        colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
        round(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
            total.patients * 100, 1
        ), "%", ")",
        sep = ""
      )
    ),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][1]
    })),
    N2 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]][1]
    })),
    OR2 = c("", sapply(res, function(x) {
      x$or[[2]][[1]][1]
    })),
    P2 = c("", sapply(res, function(x) {
      x$p[[2]][[1]][1]
    })),
    check.names = FALSE
  )
)

### CTAB score

# perform testing
immune.df$log_CTAB <- log(immune.df$CTAB + 1)
var <- "log_CTAB"
ref <- c(2, 2)
log.res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = immune.df
)
var <- "CTAB"
ref <- c(2, 2)
res <- quantStratTest(
  var = var, strata = c("male", "female"), ref = ref,
  covars = c("tissue_status", "histology_group"),
  data.df = immune.df
)

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = "CTAB score (Mean±SD)",
    N = nrow(immune.df[!is.na(immune.df[, var]), ]),
    `Summary stats` = paste(
      round(mean(na.omit(immune.df[, var])), 1),
      round(sd(na.omit(immune.df[, var])), 1),
      sep = "±"
    ),
    N1 = res$n[[1]][1],
    `N1 summary stats` = res$stats[[1]][1],
    N2 = res$n[[2]][1],
    `N2 summary stats` = res$stats[[2]][1],
    OR2 = log.res$beta[[2]],
    P2 = log.res$p[[2]],
    check.names = FALSE
  )
)

### CTAB group high, low

# create data for testing
total.patients <- length(immune.df[!is.na(immune.df$CTAB_interp), "de_id"])
test.data <- data.frame(
  patient.df,
  High = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$CTAB_interp == "High"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$CTAB_interp)], NA, 1
    )
  ),
  Low = ifelse(
    patient.df$de_id %in% immune.df$de_id[immune.df$CTAB_interp == "Low"], 0,
    ifelse(
      !(patient.df$de_id %in% immune.df$de_id) |
        patient.df$de_id %in% immune.df$de_id[is.na(immune.df$CTAB_interp)], NA, 1
    )
  ),
  check.names = FALSE
)

# perform testing
var <- c("High", "Low")
ref <- c(2, 2)
res <- list()
for (j in var) {
  res[[j]] <- catStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("CTAB score level (N, %)", var),
    N = c(total.patients, rep("", length(var))),
    `Summary stats` = c(
      "",
      paste(
        colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
        round(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])) /
            total.patients * 100, 1
        ), "%", ")",
        sep = ""
      )
    ),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]][1]
    })),
    N2 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]][1]
    })),
    OR2 = c("", sapply(res, function(x) {
      x$or[[2]][[1]][1]
    })),
    P2 = c("", sapply(res, function(x) {
      x$p[[2]][[1]][1]
    })),
    check.names = FALSE
  )
)

### write out results

# add worksheet, write data, and format output
addWorksheet(wb, "Males vs Females")

writeData(wb, "Males vs Females", results, keepNA = TRUE, colNames = FALSE)

setColWidths(
  wb, "Males vs Females",
  cols = seq_len(ncol(results)),
  widths = c(32, 5, 15, rep(c(5, 14), 2), 20, 11)
)

addStyle(
  wb, "Males vs Females",
  cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
  gridExpand = TRUE, style = left_just, stack = TRUE
)

addStyle(
  wb, "Males vs Females",
  cols = 1,
  rows = c(
    which(results$Variable == "Very high (≥20)"):which(results$Variable == "Not high (<10)"),
    which(results$Variable == "High (≥50%)"):which(results$Variable == "Negative (<1%)"),
    which(results$Variable == "Strong"):which(results$Variable == "Weak"),
    which(results$Variable == "High")[1]:which(results$Variable == "Poor"),
    which(results$Variable == "High")[2]:which(results$Variable == "Low")
  ),
  gridExpand = TRUE, style = center, stack = TRUE
)

mergeCells(wb, "Males vs Females", cols = c(2, 3), rows = 1)
mergeCells(wb, "Males vs Females", cols = c(4:5), rows = 1)
mergeCells(wb, "Males vs Females", cols = c(6:7), rows = 1)

addStyle(
  wb, "Males vs Females",
  cols = seq_len(ncol(results)), rows = 1:2,
  gridExpand = TRUE, style = bold, stack = TRUE
)

addStyle(
  wb, "Males vs Females",
  cols = seq_len(ncol(results)),
  rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
  style = horizontal_border_med, stack = TRUE
)

addStyle(
  wb, "Males vs Females",
  cols = seq_len(ncol(results)),
  rows = c(
    grep("TMB", results$Variable),
    grep("PD-L1", results$Variable),
    grep("TIGS", results$Variable),
    grep("CP", results$Variable),
    grep("CTAB", results$Variable)
  ),
  gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
)

# convert numbers from strings back to numbers
convertNum(results, wb, "Males vs Females", FALSE)

# save workbook and table of results
saveWorkbook(
  wb, "3_Immune_related_features/Immune_marker_signature_associations.xlsx",
  overwrite = TRUE
)

# plot distributions of significant markers/signatures per age group
plot.data <- data.frame(
  de_id = patient.df$de_id,
  Sex = patient.df$patient_sex,
  TMB = patient.df$TMB,
  TIGS = immune.df$TIGS,
  CP = immune.df$CP,
  CTAB = immune.df$CTAB,
  check.names = FALSE
)
plot.data <- unique(plot.data[plot.data$Sex != "Unspecified", ])
pvals <- data.frame(
  `Sex group 1` = "Male",
  `Sex group 2` = "Female",
  TMB_labels = ifelse(
    as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), "P2"]) < 0.0001, "****",
    ifelse(
      as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), "P2"]) < 0.001, "***",
      ifelse(
        as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), "P2"]) < 0.01, "**",
        ifelse(
          as.numeric(results[grep("TMB \\(Mut/Mb)", results$Variable), "P2"]) < 0.05, "*", "ns"
        )
      )
    )
  ),
  TIGS_labels = ifelse(
    as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), "P2"]) < 0.0001, "****",
    ifelse(
      as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), "P2"]) < 0.001, "***",
      ifelse(
        as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), "P2"]) < 0.01, "**",
        ifelse(
          as.numeric(results[grep("TIGS score \\(Mean±SD)", results$Variable), "P2"]) < 0.05, "*", "ns"
        )
      )
    )
  ),
  CP_labels = ifelse(
    as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), "P2"]) < 0.0001, "****",
    ifelse(
      as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), "P2"]) < 0.001, "***",
      ifelse(
        as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), "P2"]) < 0.01, "**",
        ifelse(
          as.numeric(results[grep("CP score \\(Mean±SD)", results$Variable), "P2"]) < 0.05, "*", "ns"
        )
      )
    )
  ),
  CTAB_labels = ifelse(
    as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), "P2"]) < 0.0001, "****",
    ifelse(
      as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), "P2"]) < 0.001, "***",
      ifelse(
        as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), "P2"]) < 0.01, "**",
        ifelse(
          as.numeric(results[grep("CTAB score \\(Mean±SD)", results$Variable), "P2"]) < 0.05, "*", "ns"
        )
      )
    )
  ),
  check.names = FALSE
)
g1 <- ggplot(
  plot.data[!is.na(plot.data$TMB), ], aes(y = TMB, x = Sex)
) +
  geom_hline(yintercept = 10, color = "grey50", linetype = "dashed") +
  geom_violin(scale = "width", fill = "grey", color = "grey") +
  geom_boxplot(
    width = 0.6, fill = "white", color = "black",
    outlier.size = 3, outlier.alpha = 0.5
  ) +
  geom_signif(
    data = data.frame(
      pvals,
      y = sapply(
        seq(1, nrow(pvals), 1) * 12,
        function(x) {
          x + max(na.omit(plot.data$TMB))
        }
      ),
      check.names = FALSE
    ),
    aes(xmin = `Sex group 1`, xmax = `Sex group 2`, y_position = y, annotations = TMB_labels),
    manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
    color = "black"
  ) +
  stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
  annotate("text", label = "High", x = 0, y = 20, color = "black", size = 7) +
  annotate("text", label = "Low", x = 0, y = 0, color = "black", size = 7) +
  annotate(
    "text",
    label = paste("N=", table(plot.data$Sex[!is.na(plot.data$TMB)]), sep = ""),
    x = c(1, 2), y = -10, color = "black", size = 7
  ) +
  coord_cartesian(
    xlim = c(0, 2),
    ylim = c(-10, max(na.omit(plot.data$TMB)) + (nrow(pvals[pvals$TMB_labels != "ns", ]) * 12))
  ) +
  theme_classic() +
  labs(y = "TMB (Mut/Mb)", x = "") +
  theme(
    text = element_text(size = 24),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_text(vjust = 1)
  )
g2 <- ggplot(
  plot.data[!is.na(plot.data$TIGS), ], aes(y = TIGS, x = Sex)
) +
  geom_hline(yintercept = 62, linetype = "dashed", color = "grey50") +
  geom_hline(yintercept = 43.72, linetype = "dashed", color = "grey50") +
  geom_violin(scale = "width", fill = "grey", color = "grey") +
  geom_boxplot(
    width = 0.6, fill = "white", color = "black",
    outlier.size = 3, outlier.alpha = 0.5
  ) +
  geom_signif(
    data = data.frame(
      pvals,
      y = sapply(
        seq(1, nrow(pvals), 1) * 8,
        function(x) {
          x + max(na.omit(plot.data$TIGS))
        }
      ),
      check.names = FALSE
    ),
    aes(xmin = `Sex group 1`, xmax = `Sex group 2`, y_position = y, annotations = TIGS_labels),
    manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
    color = "black"
  ) +
  stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
  annotate("text", label = "Strong", x = 0, y = 70, color = "black", size = 7) +
  annotate("text", label = "Moderate", x = 0, y = 50, color = "black", size = 7) +
  annotate("text", label = "Weak", x = 0, y = 35, color = "black", size = 7) +
  annotate(
    "text",
    label = paste("N=", table(plot.data$Sex[!is.na(plot.data$TIGS)]), sep = ""),
    x = c(1, 2), y = -5, color = "black", size = 7
  ) +
  coord_cartesian(
    xlim = c(0, 2),
    ylim = c(-10, max(na.omit(plot.data$TIGS)) + (nrow(pvals[pvals$TIGS_labels != "ns", ]) * 8))
  ) +
  theme_classic() +
  labs(y = "TIGS score", x = "") +
  theme(
    text = element_text(size = 24),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_text(vjust = 1)
  )
g3 <- ggplot(
  plot.data[!is.na(plot.data$CP), ], aes(y = CP, x = Sex)
) +
  geom_hline(yintercept = 66, linetype = "dashed", color = "grey50") +
  geom_hline(yintercept = 33, linetype = "dashed", color = "grey50") +
  geom_violin(scale = "width", fill = "grey", color = "grey") +
  geom_boxplot(
    width = 0.6, fill = "white", color = "black",
    outlier.size = 3, outlier.alpha = 0.5
  ) +
  geom_signif(
    data = data.frame(
      pvals[pvals$CP_labels != "ns", ],
      y = sapply(
        seq(1, nrow(pvals[pvals$CP_labels != "ns", ]), 1) * 8,
        function(x) {
          x + max(na.omit(plot.data$CP))
        }
      ),
      check.names = FALSE
    ),
    aes(xmin = `Sex group 1`, xmax = `Sex group 2`, y_position = y, annotations = CP_labels),
    manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
    color = "black"
  ) +
  stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
  annotate("text", label = "High", x = 0, y = 74, color = "black", size = 7) +
  annotate("text", label = "Moderate", x = 0, y = 42, color = "black", size = 7) +
  annotate("text", label = "Poor", x = 0, y = 25, color = "black", size = 7) +
  annotate(
    "text",
    label = paste("N=", table(plot.data$Sex[!is.na(plot.data$CP)]), sep = ""),
    x = c(1, 2), y = -7, color = "black", size = 7
  ) +
  coord_cartesian(
    xlim = c(0, 2),
    ylim = c(-10, max(na.omit(plot.data$CP)) + (nrow(pvals[pvals$CP_labels != "ns", ]) * 8))
  ) +
  theme_classic() +
  labs(y = "CP score") +
  theme(
    text = element_text(size = 24),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_text(vjust = 1)
  )
g4 <- ggplot(
  plot.data[!is.na(plot.data$CTAB), ], aes(y = CTAB, x = Sex)
) +
  geom_hline(yintercept = 171, linetype = "dashed", color = "grey50") +
  geom_violin(scale = "width", fill = "grey", color = "grey") +
  geom_boxplot(
    width = 0.6, fill = "white", color = "black",
    outlier.size = 3, outlier.alpha = 0.5
  ) +
  geom_signif(
    data = data.frame(
      pvals[pvals$CTAB_labels != "ns", ],
      y = sapply(
        seq(1, nrow(pvals[pvals$CTAB_labels != "ns", ]), 1) * 90,
        function(x) {
          x + max(na.omit(plot.data$CTAB))
        }
      ),
      check.names = FALSE
    ),
    aes(xmin = `Sex group 1`, xmax = `Sex group 2`, y_position = y, annotations = CTAB_labels),
    manual = TRUE, tip_length = 0, size = 0.5, textsize = 8, vjust = 0.6,
    color = "black"
  ) +
  stat_summary(fun.data = "mean_cl_normal", color = labcorp.col[1], size = 1, linewidth = 1) +
  annotate("text", label = "High", x = 0, y = 250, color = "black", size = 7) +
  annotate("text", label = "Low", x = 0, y = 100, color = "black", size = 7) +
  annotate(
    "text",
    label = paste("N=", table(plot.data$Sex[!is.na(plot.data$CTAB)]), sep = ""),
    x = c(1, 2), y = -70, color = "black", size = 7
  ) +
  coord_cartesian(
    xlim = c(0, 2),
    ylim = c(-70, max(na.omit(plot.data$CTAB)) + (nrow(pvals[pvals$CTAB_labels != "ns", ]) * 90))
  ) +
  theme_classic() +
  labs(y = "CTAB score") +
  theme(
    text = element_text(size = 24),
    axis.title.y = element_text(vjust = 1)
  )
g <- ggarrange(
  g1, NULL, g2, NULL, g3, NULL, g4,
  nrow = 7, ncol = 1, heights = c(1, 0, 1, 0, 1, 0, 1.2), align = "v"
)
ggsave(
  paste(
    "3_Immune_related_features/Immune_marker_signature_associations_males_vs_females.pdf",
    sep = ""
  ), g,
  device = "pdf", width = 5, height = 15, limitsize = FALSE
)
```

### Gene expression of individual immune genes

```{r immune-gene-expression}
# define groups to run analyses and generate plots for and their file names
groups <- c("All patients", "Male", "Female")
file.names <- c("all_patients", "males", "females")
clinical.genes <- c(
  "ADORA2A", "CD2", "ENTPD1", "CD80", "CXCR6", "ICOS", "KLRD1", "MX1",
  "CD274", "TBX21", "TLR9", "BTLA", "MS4A1", "CD4", "CD86", "DDX58",
  "ICOSLG", "LAG3", "NECTIN2", "PDCD1LG2", "TGFB1", "TNF", "CCL2", "CD27",
  "CD40", "CSF1R", "FOXP3", "IDO1", "PVR", "TIGIT", "TNFRSF14",
  "CCR2", "CD28", "CD40LG", "CTLA4", "GATA3", "IFNG", "TNFRSF4", "CD244",
  "HAVCR2", "C10orf54", "TNFRSF9", "CD3", "CD68", "CXCL10", "TNFRSF18",
  "TNFSF4", "TLR7", "CD163", "CD38", "CD8", "CXCR2", "GZMB", "IL1B",
  "PDCD1", "STAT1", "TLR8", "IL10", "CTAG1B", "CTAG2", "MAGEA1", "MAGEA3",
  "MAGEA4", "SSX2"
)

### original run ###

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      N = "All patients", `Summary stats` = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Gene",
      N = "N", `Summary stats` = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "Beta", P1 = "FDR q-value",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "Beta", P2 = "FDR q-value",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "Beta", P3 = "FDR q-value",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "Beta", P4 = "FDR q-value",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "Beta", P5 = "FDR q-value",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "Beta", P6 = "FDR q-value",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      N = nrow(sub.patient.df), `Summary stats` = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  # create data for testing
  total.patients <- sum(!(sub.patient.df$RNA_Expression %in% c("Fail", "Not Performed")))
  test.data <- merge(
    sub.patient.df,
    sub.immune.df[, grep("de_id|nrpm", colnames(sub.immune.df))],
    by = "de_id"
  )
  var <- colnames(test.data[
    ,
    grep("ABCF1", colnames(test.data)):grep("ZEB1", colnames(test.data))
  ])
  log.test.data <- test.data
  log.test.data[, var] <- log(log.test.data[, var] + 1)

  # perform testing
  ref <- rep("≥65", length(age_strat))
  log.res <- list()
  for (j in var) {
    log.res[[j]] <- quantStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = log.test.data
    )
  }
  res <- list()
  for (j in var) {
    res[[j]] <- quantStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Gene expression nRPM (Mean±SD)", gsub("_nrpm", "", var)),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c("", paste(
        apply(test.data[, var], 2, function(x) {
          round(mean(na.omit(x)), 1)
        }),
        apply(test.data[, var], 2, function(x) {
          round(sd(na.omit(x)), 1)
        }),
        sep = "±"
      )),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[2]]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]]
      })),
      OR2 = c("", sapply(log.res, function(x) {
        x$beta[[1]][[1]]
      })),
      P2 = c("", sapply(log.res, function(x) {
        x$p[[1]][[1]]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]]
      })),
      OR3 = c("", sapply(log.res, function(x) {
        x$beta[[2]][[1]]
      })),
      P3 = c("", sapply(log.res, function(x) {
        x$p[[2]][[1]]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]]
      })),
      OR4 = c("", sapply(log.res, function(x) {
        x$beta[[3]][[1]]
      })),
      P4 = c("", sapply(log.res, function(x) {
        x$p[[3]][[1]]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]]
      })),
      OR5 = c("", sapply(log.res, function(x) {
        x$beta[[4]][[1]]
      })),
      P5 = c("", sapply(log.res, function(x) {
        x$p[[4]][[1]]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]]
      })),
      OR6 = c("", sapply(log.res, function(x) {
        x$beta[[5]][[1]]
      })),
      P6 = c("", sapply(log.res, function(x) {
        x$p[[5]][[1]]
      })),
      Ptrend = c("", formatC(sapply(log.res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### multiple testing correction

  # adjust p-values for multiple testing
  for (j in grep("P", colnames(results))) {
    if (colnames(results)[j] != "P1") {
      results[!(results[, j] %in% c("FDR q-value", "P for trend", "-", "")), j] <- formatC(
        p.adjust(
          as.numeric(results[!(results[, j] %in% c("FDR q-value", "P for trend", "-", "")), j]),
          method = "BH"
        ),
        digits = 1, format = "e"
      )
    }
  }

  ### write out results

  # create workbook
  if (i == 1) {
    wb <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb, groups[i])

  writeData(wb, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(33, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = 1,
    rows = (grep("^Gene expression", results$Variable) + 1):nrow(results),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb, groups[i], cols = c(2, 3), rows = 1)
  mergeCells(wb, groups[i], cols = c(4:7), rows = 1)
  mergeCells(wb, groups[i], cols = c(8:11), rows = 1)
  mergeCells(wb, groups[i], cols = c(12:15), rows = 1)
  mergeCells(wb, groups[i], cols = c(16:19), rows = 1)
  mergeCells(wb, groups[i], cols = c(20:23), rows = 1)
  mergeCells(wb, groups[i], cols = c(24:27), rows = 1)

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = grep("^Gene expression", results$Variable),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb, groups[i], FALSE)

  # save workbook and table of results
  saveWorkbook(
    wb, "3_Immune_related_features/Immune_gex_associations.xlsx",
    overwrite = TRUE
  )

  # plot results as volcano plot
  plot.data <- data.frame(
    Gene = results$Variable[5:nrow(results)],
    Coefficient = rowMeans(cbind(
      as.numeric(sapply(strsplit(results$OR2[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR3[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR4[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR5[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR6[5:nrow(results)], " "), function(x) {
        x[1]
      }))
    )),
    P = as.numeric(results$Ptrend[5:nrow(results)]),
    check.names = FALSE
  )

  plot.data$color[plot.data$Coefficient < 0 & plot.data$P < 0.25] <- labcorp.col[3]
  plot.data$color[plot.data$Coefficient > 0 & plot.data$P < 0.25] <- labcorp.col[1]
  plot.data$color[plot.data$P >= 0.25] <- "grey"

  plot.data$labels <- ""
  plot.data$labels[
    plot.data$P < 0.25 & plot.data$Gene %in% clinical.genes
  ] <- plot.data$Gene[
    plot.data$P < 0.25 & plot.data$Gene %in% clinical.genes
  ]

  plot.data <- merge(plot.data, gene.list, by = "Gene", all = TRUE)
  plot.data$Signature[is.na(plot.data$Signature)] <- "NA"
  plot.data$Signature <- factor(
    plot.data$Signature,
    levels = c("TIGS", "CTAB", "CP", "NA")
  )

  plot.data$`Clinical significance` <- ifelse(
    plot.data$Gene %in% clinical.genes,
    "Potential immunotherapy target",
    "Not yet established as a target"
  )

  breaks <- seq(
    min(round(plot.data$Coefficient, 1)) - 0.05,
    max(round(plot.data$Coefficient, 1)) + 0.05,
    0.1
  )
  break_labels <- c(
    paste(round(1 / exp(breaks[breaks < 0]), 1), "x", sep = ""),
    paste(round(exp(breaks[breaks >= 0]), 1), "x", sep = "")
  )

  set.seed(1234)
  g <- ggplot(data = plot.data, aes(x = Coefficient, y = -log10(P), label = labels)) +
    geom_vline(xintercept = 0, linetype = "dashed") +
    geom_hline(yintercept = -log10(0.25), linetype = "dashed") +
    geom_point(
      aes(shape = Signature, color = `Clinical significance`),
      fill = plot.data$color, size = 5, alpha = 0.75,
      stroke = ifelse(plot.data$Gene %in% clinical.genes, 1.5, 0.5)
    ) +
    geom_label_repel(
      force = 5, force_pull = 0, min.segment.length = 0.5, box.padding = 0.2,
      max.overlaps = Inf, size = 4, color = plot.data$color, segment.color = "black"
    ) +
    scale_x_continuous(breaks = breaks, labels = break_labels) +
    scale_shape_manual(values = c(24, 23, 22, 21)) +
    scale_color_manual(
      breaks = c("Potential immunotherapy target", "Not yet established as a target"),
      values = c("black", "black")
    ) +
    annotate(
      "label",
      label = "Enriched in younger\npatient tumors",
      x = 0.15, y = 0, size = 6
    ) +
    annotate(
      "label",
      label = "Enriched in older\npatient tumors",
      x = -0.15, y = 0, size = 6
    ) +
    coord_cartesian(
      ylim = c(0, 5),
      xlim = c(
        min(round(plot.data$Coefficient, 1)) - 0.05,
        max(round(plot.data$Coefficient, 1)) + 0.05
      )
    ) +
    theme_bw() +
    theme(
      text = element_text(size = 24),
      legend.text = element_text(size = 16),
      legend.title = element_text(size = 16),
      legend.position = c(0.75, 0.8),
      legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
    ) +
    guides(
      color = guide_legend(
        override.aes = list(
          pch = 21, fill = "white", color = "black", stroke = c(2, 0.5)
        )
      )
    ) +
    labs(y = "-log10 Adjusted P-value", x = "Estimated fold change")
  ggsave(
    paste(
      "3_Immune_related_features/Immune_gex_associations_",
      file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 10, height = 8, limitsize = FALSE
  )

  # plot overlapping genes between all patients and males/females
  if (i == 1) {
    degs <- plot.data$Gene[plot.data$P < 0.25]
  } else {
    plot.list <- list(degs, plot.data$Gene[plot.data$P < 0.25])
    names(plot.list) <- c("1", "2")
    g <- ggvenn(
      plot.list,
      fill_color = rep(labcorp.col[7], 2), fill_alpha = 0.25, stroke_color = "white",
      text_size = 7, auto_scale = FALSE
    )
    g$layers[[3]]$data$x <- c(-2, 2)
    ggsave(
      paste(
        "3_Immune_related_features/Immune_gex_associations_",
        file.names[i], "_overlap.pdf",
        sep = ""
      ), g,
      device = "pdf", width = 7, height = 3, limitsize = FALSE
    )
  }
}

### adjusting for ALK/EGFR positivity ###

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      N = "All patients", `Summary stats` = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Gene",
      N = "N", `Summary stats` = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "Beta", P1 = "FDR q-value",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "Beta", P2 = "FDR q-value",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "Beta", P3 = "FDR q-value",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "Beta", P4 = "FDR q-value",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "Beta", P5 = "FDR q-value",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "Beta", P6 = "FDR q-value",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      N = nrow(sub.patient.df), `Summary stats` = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  # create data for testing
  total.patients <- sum(!(sub.patient.df$RNA_Expression %in% c("Fail", "Not Performed")))
  test.data <- merge(
    sub.patient.df,
    sub.immune.df[, grep("de_id|nrpm", colnames(sub.immune.df))],
    by = "de_id"
  )
  var <- colnames(test.data[
    ,
    grep("ABCF1", colnames(test.data)):grep("ZEB1", colnames(test.data))
  ])
  log.test.data <- test.data
  log.test.data[, var] <- log(log.test.data[, var] + 1)

  # perform testing
  ref <- rep("≥65", length(age_strat))
  log.res <- list()
  for (j in var) {
    log.res[[j]] <- quantStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = log.test.data
    )
  }
  res <- list()
  for (j in var) {
    res[[j]] <- quantStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group", "ALK_EGFR"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("Gene expression nRPM (Mean±SD)", gsub("_nrpm", "", var)),
      N = c(total.patients, rep("", length(var))),
      `Summary stats` = c("", paste(
        apply(test.data[, var], 2, function(x) {
          round(mean(na.omit(x)), 1)
        }),
        apply(test.data[, var], 2, function(x) {
          round(sd(na.omit(x)), 1)
        }),
        sep = "±"
      )),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[2]]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]]
      })),
      OR2 = c("", sapply(log.res, function(x) {
        x$beta[[1]][[1]]
      })),
      P2 = c("", sapply(log.res, function(x) {
        x$p[[1]][[1]]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]]
      })),
      OR3 = c("", sapply(log.res, function(x) {
        x$beta[[2]][[1]]
      })),
      P3 = c("", sapply(log.res, function(x) {
        x$p[[2]][[1]]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]]
      })),
      OR4 = c("", sapply(log.res, function(x) {
        x$beta[[3]][[1]]
      })),
      P4 = c("", sapply(log.res, function(x) {
        x$p[[3]][[1]]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]]
      })),
      OR5 = c("", sapply(log.res, function(x) {
        x$beta[[4]][[1]]
      })),
      P5 = c("", sapply(log.res, function(x) {
        x$p[[4]][[1]]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]]
      })),
      OR6 = c("", sapply(log.res, function(x) {
        x$beta[[5]][[1]]
      })),
      P6 = c("", sapply(log.res, function(x) {
        x$p[[5]][[1]]
      })),
      Ptrend = c("", formatC(sapply(log.res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  ### multiple testing correction

  # adjust p-values for multiple testing
  for (j in grep("P", colnames(results))) {
    if (colnames(results)[j] != "P1") {
      results[!(results[, j] %in% c("FDR q-value", "P for trend", "-", "")), j] <- formatC(
        p.adjust(
          as.numeric(results[!(results[, j] %in% c("FDR q-value", "P for trend", "-", "")), j]),
          method = "BH"
        ),
        digits = 1, format = "e"
      )
    }
  }

  ### write out results

  # create workbook
  if (i == 1) {
    wb2 <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb2, groups[i])

  writeData(wb2, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb2, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(33, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb2, groups[i],
    cols = 1,
    rows = (grep("^Gene expression", results$Variable) + 1):nrow(results),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb2, groups[i], cols = c(2, 3), rows = 1)
  mergeCells(wb2, groups[i], cols = c(4:7), rows = 1)
  mergeCells(wb2, groups[i], cols = c(8:11), rows = 1)
  mergeCells(wb2, groups[i], cols = c(12:15), rows = 1)
  mergeCells(wb2, groups[i], cols = c(16:19), rows = 1)
  mergeCells(wb2, groups[i], cols = c(20:23), rows = 1)
  mergeCells(wb2, groups[i], cols = c(24:27), rows = 1)

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb2, groups[i],
    cols = seq_len(ncol(results)),
    rows = grep("^Gene expression", results$Variable),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb2, groups[i], FALSE)

  # save workbook and table of results
  saveWorkbook(
    wb2, "3_Immune_related_features/ALK_EGFR_adjusted/Immune_gex_associations_ALK_EGFR_adj.xlsx",
    overwrite = TRUE
  )

  # plot results as volcano plot
  plot.data <- data.frame(
    Gene = results$Variable[5:nrow(results)],
    Coefficient = rowMeans(cbind(
      as.numeric(sapply(strsplit(results$OR2[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR3[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR4[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR5[5:nrow(results)], " "), function(x) {
        x[1]
      })),
      as.numeric(sapply(strsplit(results$OR6[5:nrow(results)], " "), function(x) {
        x[1]
      }))
    )),
    P = as.numeric(results$Ptrend[5:nrow(results)]),
    check.names = FALSE
  )

  plot.data$color[plot.data$Coefficient < 0 & plot.data$P < 0.25] <- labcorp.col[3]
  plot.data$color[plot.data$Coefficient > 0 & plot.data$P < 0.25] <- labcorp.col[1]
  plot.data$color[plot.data$P >= 0.25] <- "grey"

  plot.data$labels <- ""
  plot.data$labels[
    plot.data$P < 0.25 & plot.data$Gene %in% clinical.genes
  ] <- plot.data$Gene[
    plot.data$P < 0.25 & plot.data$Gene %in% clinical.genes
  ]

  plot.data <- merge(plot.data, gene.list, by = "Gene", all = TRUE)
  plot.data$Signature[is.na(plot.data$Signature)] <- "NA"
  plot.data$Signature <- factor(
    plot.data$Signature,
    levels = c("TIGS", "CTAB", "CP", "NA")
  )

  plot.data$`Clinical significance` <- ifelse(
    plot.data$Gene %in% clinical.genes,
    "Potential immunotherapy target",
    "Not yet established as a target"
  )

  breaks <- seq(
    min(round(plot.data$Coefficient, 1)) - 0.05,
    max(round(plot.data$Coefficient, 1)) + 0.05,
    0.1
  )
  break_labels <- c(
    paste(round(1 / exp(breaks[breaks < 0]), 1), "x", sep = ""),
    paste(round(exp(breaks[breaks >= 0]), 1), "x", sep = "")
  )

  set.seed(1234)
  g <- ggplot(data = plot.data, aes(x = Coefficient, y = -log10(P), label = labels)) +
    geom_vline(xintercept = 0, linetype = "dashed") +
    geom_hline(yintercept = -log10(0.25), linetype = "dashed") +
    geom_point(
      aes(shape = Signature, color = `Clinical significance`),
      fill = plot.data$color, size = 5, alpha = 0.75,
      stroke = ifelse(plot.data$Gene %in% clinical.genes, 1.5, 0.5)
    ) +
    geom_label_repel(
      force = 5, force_pull = 0, min.segment.length = 0.5, box.padding = 0.2,
      max.overlaps = Inf, size = 4, color = plot.data$color, segment.color = "black"
    ) +
    scale_x_continuous(breaks = breaks, labels = break_labels) +
    scale_shape_manual(values = c(24, 23, 22, 21)) +
    scale_color_manual(
      breaks = c("Potential immunotherapy target", "Not yet established as a target"),
      values = c("black", "black")
    ) +
    annotate(
      "label",
      label = "Enriched in younger\npatient tumors",
      x = 0.15, y = 0, size = 6
    ) +
    annotate(
      "label",
      label = "Enriched in older\npatient tumors",
      x = -0.15, y = 0, size = 6
    ) +
    coord_cartesian(
      ylim = c(0, 5),
      xlim = c(
        min(round(plot.data$Coefficient, 1)) - 0.05,
        max(round(plot.data$Coefficient, 1)) + 0.05
      )
    ) +
    theme_bw() +
    theme(
      text = element_text(size = 24),
      legend.text = element_text(size = 16),
      legend.title = element_text(size = 16),
      legend.position = c(0.75, 0.8),
      legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
    ) +
    guides(
      color = guide_legend(
        override.aes = list(
          pch = 21, fill = "white", color = "black", stroke = c(2, 0.5)
        )
      )
    ) +
    labs(y = "-log10 Adjusted P-value", x = "Estimated fold change")
  ggsave(
    paste(
      "3_Immune_related_features/ALK_EGFR_adjusted/Immune_gex_associations_ALK_EGFR_adj_",
      file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 10, height = 8, limitsize = FALSE
  )

  # plot overlapping genes between all patients and males/females
  if (i == 1) {
    degs <- plot.data$Gene[plot.data$P < 0.25]
  } else {
    plot.list <- list(degs, plot.data$Gene[plot.data$P < 0.25])
    names(plot.list) <- c("1", "2")
    g <- ggvenn(
      plot.list,
      fill_color = rep(labcorp.col[7], 2), fill_alpha = 0.25, stroke_color = "white",
      text_size = 7, auto_scale = FALSE
    )
    g$layers[[3]]$data$x <- c(-2, 2)
    ggsave(
      paste(
        "3_Immune_related_features/ALK_EGFR_adjusted/Immune_gex_associations_ALK_EGFR_adj_",
        file.names[i], "_overlap.pdf",
        sep = ""
      ), g,
      device = "pdf", width = 7, height = 3, limitsize = FALSE
    )
  }
}

### re-run analysis and plotting for testing males vs females ###

# create result data.frame
results <- data.frame()
results <- rbind(
  results,
  data.frame(
    Variable = "",
    N = "All patients", `Summary stats` = "",
    N1 = "Males", `N1 summary stats` = "",
    N2 = "Females", `N2 summary stats` = "", OR = "", P = "",
    check.names = FALSE
  )
)
results <- rbind(
  results,
  data.frame(
    Variable = "Gene",
    N = "N", `Summary stats` = "Summary stats",
    N1 = "N", `N1 summary stats` = "Summary stats",
    N2 = "N", `N2 summary stats` = "Summary stats", OR = "Beta", P = "FDR q-value",
    check.names = FALSE
  )
)

# get total number of patients
results <- rbind(
  results,
  data.frame(
    Variable = "Total number of patients",
    N = nrow(patient.df), `Summary stats` = "-",
    N1 = table(patient.df$patient_sex)[2], `N1 summary stats` = "-",
    N2 = table(patient.df$patient_sex)[1], `N2 summary stats` = "-", OR = "-", P = "-",
    check.names = FALSE
  )
)

# create data for testing
total.patients <- sum(!(patient.df$RNA_Expression %in% c("Fail", "Not Performed")))
test.data <- merge(
  patient.df[patient.df$patient_sex != "Unspecified", ],
  immune.df[, grep("de_id|nrpm", colnames(sub.immune.df))],
  by = "de_id"
)
var <- colnames(test.data[
  ,
  grep("ABCF1", colnames(test.data)):grep("ZEB1", colnames(test.data))
])
log.test.data <- test.data
log.test.data[, var] <- log(log.test.data[, var] + 1)

# perform testing
ref <- c(2, 2)
log.res <- list()
for (j in var) {
  log.res[[j]] <- quantStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = log.test.data
  )
}
res <- list()
for (j in var) {
  res[[j]] <- quantStratTest(
    var = j, strata = c("male", "female"), ref = ref,
    covars = c("tissue_status", "histology_group"),
    data.df = test.data
  )
}

# add results to result data.frame
results <- rbind(
  results,
  data.frame(
    Variable = c("Gene expression nRPM (Mean±SD)", gsub("_nrpm", "", var)),
    N = c(total.patients, rep("", length(var))),
    `Summary stats` = c("", paste(
      apply(test.data[, var], 2, function(x) {
        round(mean(na.omit(x)), 1)
      }),
      apply(test.data[, var], 2, function(x) {
        round(sd(na.omit(x)), 1)
      }),
      sep = "±"
    )),
    N1 = c(sapply(res, function(x) {
      x$n[[1]][1]
    })[1], rep("", length(var))),
    `N1 summary stats` = c("", sapply(res, function(x) {
      x$stats[[1]][[1]]
    })),
    N2 = c(sapply(res, function(x) {
      x$n[[2]][1]
    })[1], rep("", length(var))),
    `N2 summary stats` = c("", sapply(res, function(x) {
      x$stats[[2]][[1]]
    })),
    OR = c("", sapply(log.res, function(x) {
      x$beta[[2]][[1]]
    })),
    P = c("", sapply(log.res, function(x) {
      x$p[[2]][[1]]
    })),
    check.names = FALSE
  )
)

### multiple testing correction

# adjust p-values for multiple testing
for (i in grep("P", colnames(results))) {
  results[!(results[, i] %in% c("FDR q-value", "-", "")), i] <- formatC(
    p.adjust(
      as.numeric(results[!(results[, i] %in% c("FDR q-value", "-", "")), i]),
      method = "BH"
    ),
    digits = 1, format = "e"
  )
}

### write out results

# add worksheet, write data, and format output
addWorksheet(wb, "Male vs Female")

writeData(wb, "Male vs Female", results, keepNA = TRUE, colNames = FALSE)

setColWidths(
  wb, "Male vs Female",
  cols = seq_len(ncol(results)),
  widths = c(33, 5, 15, rep(c(5, 14), 2), 20, 11)
)

addStyle(
  wb, "Male vs Female",
  cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
  gridExpand = TRUE, style = left_just, stack = TRUE
)

addStyle(
  wb, "Male vs Female",
  cols = 1,
  rows = (grep("^Gene expression", results$Variable) + 1):nrow(results),
  gridExpand = TRUE, style = center, stack = TRUE
)

mergeCells(wb, "Male vs Female", cols = c(2, 3), rows = 1)
mergeCells(wb, "Male vs Female", cols = c(4:5), rows = 1)
mergeCells(wb, "Male vs Female", cols = c(6:7), rows = 1)

addStyle(
  wb, "Male vs Female",
  cols = seq_len(ncol(results)), rows = 1:2,
  gridExpand = TRUE, style = bold, stack = TRUE
)

addStyle(
  wb, "Male vs Female",
  cols = seq_len(ncol(results)),
  rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
  style = horizontal_border_med, stack = TRUE
)

addStyle(
  wb, "Male vs Female",
  cols = seq_len(ncol(results)),
  rows = grep("^Gene expression", results$Variable),
  gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
)

# convert numbers from strings back to numbers
convertNum(results, wb, "Male vs Female", FALSE)

# save workbook and table of results
saveWorkbook(
  wb, "3_Immune_related_features/Immune_gex_associations.xlsx",
  overwrite = TRUE
)

# plot results as volcano plot
plot.data <- data.frame(
  Gene = results$Variable[5:nrow(results)],
  Coefficient = -as.numeric(sapply(
    strsplit(results$OR[5:nrow(results)], " "), function(x) {
      x[1]
    }
  )),
  P = as.numeric(results$P[5:nrow(results)]),
  check.names = FALSE
)

plot.data$color[plot.data$Coefficient < 0 & plot.data$P < 0.25] <- labcorp.col[3]
plot.data$color[plot.data$Coefficient > 0 & plot.data$P < 0.25] <- labcorp.col[1]
plot.data$color[plot.data$P >= 0.25] <- "grey"

plot.data$labels <- ""
plot.data$labels[
  (plot.data$P < 0.25 & plot.data$Gene %in% clinical.genes) | plot.data$P < 1E-15
] <- plot.data$Gene[
  (plot.data$P < 0.25 & plot.data$Gene %in% clinical.genes) | plot.data$P < 1E-15
]

plot.data <- merge(plot.data, gene.list, by = "Gene", all = TRUE)
plot.data$Signature[is.na(plot.data$Signature)] <- "NA"
plot.data$Signature <- factor(
  plot.data$Signature,
  levels = c("TIGS", "CTAB", "CP", "NA")
)

plot.data$`Clinical significance` <- ifelse(
  plot.data$Gene %in% clinical.genes,
  "Potential immunotherapy target",
  "Not yet established as a target"
)

breaks <- seq(
  min(round(plot.data$Coefficient, 1)) - 0.05,
  max(round(plot.data$Coefficient, 1)) + 0.05,
  0.1
)
break_labels <- c(
  paste(round(1 / exp(breaks[breaks < 0]), 1), "x", sep = ""),
  paste(round(exp(breaks[breaks >= 0]), 1), "x", sep = "")
)

set.seed(1234)
g <- ggplot(data = plot.data, aes(x = Coefficient, y = -log10(P), label = labels)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  geom_hline(yintercept = -log10(0.25), linetype = "dashed") +
  geom_point(
    aes(shape = Signature, color = `Clinical significance`),
    fill = plot.data$color, size = 5, alpha = 0.75,
    stroke = ifelse(plot.data$Gene %in% clinical.genes, 1.5, 0.5)
  ) +
  geom_label_repel(
    force = 5, force_pull = 0, min.segment.length = 0.5, box.padding = 0.2,
    max.overlaps = 40, size = 4, color = plot.data$color, segment.color = "black"
  ) +
  scale_x_continuous(breaks = breaks, labels = break_labels) +
  scale_shape_manual(values = c(24, 23, 22, 21)) +
  scale_color_manual(
    breaks = c("Potential immunotherapy target", "Not yet established as a target"),
    values = c("black", "black")
  ) +
  annotate(
    "label",
    label = "Enriched in male\npatient tumors",
    x = 0.15, y = 0, size = 6
  ) +
  annotate(
    "label",
    label = "Enriched in female\npatient tumors",
    x = -0.15, y = 0, size = 6
  ) +
  coord_cartesian(
    xlim = c(
      min(round(plot.data$Coefficient, 1)) - 0.05,
      max(round(plot.data$Coefficient, 1)) + 0.05
    )
  ) +
  theme_bw() +
  theme(
    text = element_text(size = 24),
    legend.text = element_text(size = 16),
    legend.title = element_text(size = 16),
    legend.position = c(0.75, 0.8),
    legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
  ) +
  guides(
    color = guide_legend(
      override.aes = list(
        pch = 21, fill = "white", color = "black", stroke = c(2, 0.5)
      )
    )
  ) +
  labs(y = "-log10 Adjusted P-value", x = "Estimated fold change")
ggsave(
  "3_Immune_related_features/Immune_gex_associations_males_vs_females.pdf", g,
  device = "pdf", width = 10, height = 8, limitsize = FALSE
)
```

### High expression of immune markers matched to clinical trials

```{r high-gex-prevalence}
# define groups to run analyses for
groups <- c("All patients", "Male", "Female")
file.names <- c("all_patients", "males", "females")
clinical.genes <- c(
  "ADORA2A_rank", "CD2_rank", "ENTPD1_rank", "CD80_rank", "CXCR6_rank", "ICOS_rank", "KLRD1_rank", "MX1_rank",
  "CD274_rank", "TBX21_rank", "TLR9_rank", "BTLA_rank", "MS4A1_rank", "CD4_rank", "CD86_rank", "DDX58_rank",
  "ICOSLG_rank", "LAG3_rank", "NECTIN2_rank", "PDCD1LG2_rank", "TGFB1_rank", "TNF_rank", "CCL2_rank", "CD27_rank", "CD40_rank", "CSF1R_rank", "FOXP3_rank", "IDO1_rank", "PVR_rank", "TIGIT_rank", "TNFRSF14_rank",
  "CCR2_rank", "CD28_rank", "CD40LG_rank", "CTLA4_rank", "GATA3_rank", "IFNG_rank", "TNFRSF4_rank", "CD244_rank",
  "HAVCR2_rank", "C10orf54_rank", "TNFRSF9_rank", "CD3_rank", "CD68_rank", "CXCL10_rank", "TNFRSF18_rank",
  "TNFSF4_rank", "TLR7_rank", "CD163_rank", "CD38_rank", "CD8_rank", "CXCR2_rank", "GZMB_rank", "IL1B_rank",
  "PDCD1_rank", "STAT1_rank", "TLR8_rank", "IL10_rank", "CTAG1B_rank", "CTAG2_rank", "MAGEA1_rank", "MAGEA3_rank",
  "MAGEA4_rank", "SSX2_rank"
)

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.patient.df <- patient.df
    sub.immune.df <- immune.df
  } else {
    sub.patient.df <- patient.df[patient.df$patient_sex == groups[i], ]
    sub.immune.df <- immune.df[immune.df$patient_sex == groups[i], ]
  }

  # create result data.frame
  results <- data.frame()
  results <- rbind(
    results,
    data.frame(
      Variable = "",
      N = "All patients", Frequency = "",
      N1 = "Age ≥65", `N1 summary stats` = "", OR1 = "", P1 = "",
      N2 = "Age <65", `N2 summary stats` = "", OR2 = "", P2 = "",
      N3 = "Age <60", `N3 summary stats` = "", OR3 = "", P3 = "",
      N4 = "Age <55", `N4 summary stats` = "", OR4 = "", P4 = "",
      N5 = "Age <50", `N5 summary stats` = "", OR5 = "", P5 = "",
      N6 = "Age <45", `N6 summary stats` = "", OR6 = "", P6 = "",
      Ptrend = "",
      check.names = FALSE
    )
  )
  results <- rbind(
    results,
    data.frame(
      Variable = "Gene",
      N = "N", Frequency = "Summary stats",
      N1 = "N", `N1 summary stats` = "Summary stats", OR1 = "OR", P1 = "FDR q-value",
      N2 = "N", `N2 summary stats` = "Summary stats", OR2 = "OR", P2 = "FDR q-value",
      N3 = "N", `N3 summary stats` = "Summary stats", OR3 = "OR", P3 = "FDR q-value",
      N4 = "N", `N4 summary stats` = "Summary stats", OR4 = "OR", P4 = "FDR q-value",
      N5 = "N", `N5 summary stats` = "Summary stats", OR5 = "OR", P5 = "FDR q-value",
      N6 = "N", `N6 summary stats` = "Summary stats", OR6 = "OR", P6 = "FDR q-value",
      Ptrend = "P for trend",
      check.names = FALSE
    )
  )

  # get total number of patients
  results <- rbind(
    results,
    data.frame(
      Variable = "Total number of patients",
      N = nrow(sub.patient.df), Frequency = "-",
      N1 = table(sub.patient.df$age_65)[2], `N1 summary stats` = "-", OR1 = "-", P1 = "-",
      N2 = table(sub.patient.df$age_65)[1], `N2 summary stats` = "-", OR2 = "-", P2 = "-",
      N3 = table(sub.patient.df$age_60)[1], `N3 summary stats` = "-", OR3 = "-", P3 = "-",
      N4 = table(sub.patient.df$age_55)[1], `N4 summary stats` = "-", OR4 = "-", P4 = "-",
      N5 = table(sub.patient.df$age_50)[1], `N5 summary stats` = "-", OR5 = "-", P5 = "-",
      N6 = table(sub.patient.df$age_45)[1], `N6 summary stats` = "-", OR6 = "-", P6 = "-",
      Ptrend = "-",
      check.names = FALSE
    )
  )

  # create data for testing
  var <- c()
  test.data <- sub.patient.df
  ref.data <- sub.immune.df[, clinical.genes]
  colnames(ref.data) <- gsub("_rank", "", colnames(ref.data))
  for (j in colnames(ref.data)) {
    test.data$feat <- ifelse(
      ref.data[, j] >= 75, 0,
      ifelse(
        !(sub.patient.df$RNA_Expression %in% c("Fail", "Not Performed")), 1, NA
      )
    )
    var <- append(var, j)
    colnames(test.data)[ncol(test.data)] <- j
  }
  var <- colnames(t(memoSort(t(abs(test.data[, var] - 1)))))
  test.data <- test.data[, c(colnames(sub.patient.df), var)]

  # perform testing
  ref <- rep("≥65", length(age_strat))
  res <- list()
  for (j in var) {
    res[[j]] <- catStratTest(
      var = j, strata = age_strat, ref = ref,
      covars = c("tissue_status", "histology_group"), trend.var = "trend_age",
      data.df = test.data
    )
  }

  # add results to result data.frame
  results <- rbind(
    results,
    data.frame(
      Variable = c("High gene expression (N, %)", var),
      N = c(total.patients, rep("", length(var))),
      Frequency = c(
        "",
        paste(
          colSums(test.data[, var] == 0 & !is.na(test.data[, var])), " ", "(",
          round(colSums(test.data[, var] == 0 & !is.na(test.data[, var])) / (total.patients) * 100, 1), "%", ")",
          sep = ""
        )
      ),
      N1 = c(sapply(res, function(x) {
        x$n[[1]][2]
      })[1], rep("", length(var))),
      `N1 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][3]
      })),
      OR1 = c("", rep("Ref", length(var))),
      P1 = c("", rep("Ref", length(var))),
      N2 = c(sapply(res, function(x) {
        x$n[[1]][1]
      })[1], rep("", length(var))),
      `N2 summary stats` = c("", sapply(res, function(x) {
        x$stats[[1]][[1]][1]
      })),
      OR2 = c("", sapply(res, function(x) {
        x$or[[1]][[1]][1]
      })),
      P2 = c("", sapply(res, function(x) {
        x$p[[1]][[1]][1]
      })),
      N3 = c(sapply(res, function(x) {
        x$n[[2]][1]
      })[1], rep("", length(var))),
      `N3 summary stats` = c("", sapply(res, function(x) {
        x$stats[[2]][[1]][1]
      })),
      OR3 = c("", sapply(res, function(x) {
        x$or[[2]][[1]][1]
      })),
      P3 = c("", sapply(res, function(x) {
        x$p[[2]][[1]][1]
      })),
      N4 = c(sapply(res, function(x) {
        x$n[[3]][1]
      })[1], rep("", length(var))),
      `N4 summary stats` = c("", sapply(res, function(x) {
        x$stats[[3]][[1]][1]
      })),
      OR4 = c("", sapply(res, function(x) {
        x$or[[3]][[1]][1]
      })),
      P4 = c("", sapply(res, function(x) {
        x$p[[3]][[1]][1]
      })),
      N5 = c(sapply(res, function(x) {
        x$n[[4]][1]
      })[1], rep("", length(var))),
      `N5 summary stats` = c("", sapply(res, function(x) {
        x$stats[[4]][[1]][1]
      })),
      OR5 = c("", sapply(res, function(x) {
        x$or[[4]][[1]][1]
      })),
      P5 = c("", sapply(res, function(x) {
        x$p[[4]][[1]][1]
      })),
      N6 = c(sapply(res, function(x) {
        x$n[[5]][1]
      })[1], rep("", length(var))),
      `N6 summary stats` = c("", sapply(res, function(x) {
        x$stats[[5]][[1]][1]
      })),
      OR6 = c("", sapply(res, function(x) {
        x$or[[5]][[1]][1]
      })),
      P6 = c("", sapply(res, function(x) {
        x$p[[5]][[1]][1]
      })),
      Ptrend = c("", formatC(sapply(res, function(x) {
        x$ptrend[1]
      }), digits = 1, format = "e")),
      check.names = FALSE
    )
  )

  # adjust p-values for multiple testing
  for (j in grep("P", colnames(results))) {
    if (colnames(results)[j] != "P1") {
      results[!(results[, j] %in%
        c("FDR q-value", "P for trend", "-", "")), j] <- formatC(
        p.adjust(
          as.numeric(results[!(results[, j] %in%
            c("FDR q-value", "P for trend", "-", "")), j]),
          method = "BH"
        ),
        digits = 1, format = "e"
      )
    }
  }

  ### write out results

  # create workbook
  if (i == 1) {
    wb <- createWorkbook()
  }

  # add worksheet, write data, and format output
  addWorksheet(wb, groups[i])

  writeData(wb, groups[i], results, keepNA = TRUE, colNames = FALSE)

  setColWidths(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    widths = c(33, 5, 15, rep(c(5, 14, 20, 11), length(age_strat) + 1), 10)
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:(nrow(results) + 1),
    gridExpand = TRUE, style = left_just, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = 1,
    rows = (grep("^High", results$Variable) + 1):nrow(results),
    gridExpand = TRUE, style = center, stack = TRUE
  )

  mergeCells(wb, groups[i], cols = c(2, 3), rows = 1)
  mergeCells(wb, groups[i], cols = c(4:7), rows = 1)
  mergeCells(wb, groups[i], cols = c(8:11), rows = 1)
  mergeCells(wb, groups[i], cols = c(12:15), rows = 1)
  mergeCells(wb, groups[i], cols = c(16:19), rows = 1)
  mergeCells(wb, groups[i], cols = c(20:23), rows = 1)
  mergeCells(wb, groups[i], cols = c(24:27), rows = 1)

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)), rows = 1:2,
    gridExpand = TRUE, style = bold, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = c(1, 3, (nrow(results) + 1)), gridExpand = TRUE,
    style = horizontal_border_med, stack = TRUE
  )

  addStyle(
    wb, groups[i],
    cols = seq_len(ncol(results)),
    rows = grep("^High", results$Variable),
    gridExpand = TRUE, style = horizontal_border_thin, stack = TRUE
  )

  # convert numbers from strings back to numbers
  convertNum(results, wb, groups[i], FALSE)

  # save workbook and table of results
  saveWorkbook(
    wb, "3_Immune_related_features/TCRs_TILs_high_gex_associations.xlsx",
    overwrite = TRUE
  )
}
```

## Outcomes-based analyses

### Retrospective survival analysis (pembrolizumab and pembrolizumab + chemotherapy)

```{r survival-analysis}
# read data
retro.df <- data.frame(read_xlsx(
  "_Data_for_analysis/CGIP_of_Young_NSCLC_2024_de_id_data.xlsx",
  na = c("NULL", "NA", "N/A"), sheet = 5
))

# create variable to stratify patients by age
retro.df$age_65 <- ifelse(retro.df$age < 65, "<65", ifelse(retro.df$age >= 65, "≥65", NA))
retro.df$trend_age <- ifelse(
  retro.df$age < 65, retro.df$age,
  ifelse(retro.df$age >= 65, 65, NA)
)

# define groups to run analyses and generate plots for and their file names
groups <- c("All patients", "Male", "Female")
file.names <- c("all_patients", "males", "females")

# run for each group
for (i in seq_along(groups)) {
  # extract needed data
  if (i == 1) {
    sub.retro.df <- retro.df
  } else {
    sub.retro.df <- retro.df[retro.df$gender == groups[i], ]
  }

  ### Overall survival

  # pembrolizumab
  test.data <- sub.retro.df[
    grepl("pembrolizumab", sub.retro.df$pembro_group),
  ]
  surv.obj <- with(test.data, Surv(survival, survival_event))
  cox.fit <- summary(coxph(surv.obj ~ age_65 + histology_group, data = test.data))
  trend.cox.fit <- summary(coxph(surv.obj ~ trend_age + histology_group, data = test.data))
  km.fit <- survfit(surv.obj ~ age_65, data = test.data)
  med.surv <- ddply(test.data, .(age_65), summarize, median = round(median(survival), 0))
  g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
    annotate(
      "label",
      label = paste(
        "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
        ", P = ", round(cox.fit$coefficients[1, 5], 2),
        "\nP for trend = ", round(trend.cox.fit$coefficients[1, 5], 2),
        sep = ""
      ),
      x = max(test.data$survival) / 1.3, y = 0.9, size = 7
    ) +
    scale_color_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median OS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median OS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_fill_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median OS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median OS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_y_continuous(
      breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
      limits = c(-0.2, 1)
    ) +
    theme_bw() +
    theme(
      text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
      legend.text = element_text(size = 16),
      legend.title = element_blank(),
      legend.spacing.y = unit(0, "pt"),
      legend.position = c(0.35, 0.1),
      legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
    ) +
    labs(x = "Time (days)", y = "Overall survival")
  ggsave(
    paste(
      "4_Survival_analysis/Pembro_overall_survival_", file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 7, height = 5, limitsize = FALSE
  )

  # pembrolizumab + chemotherapy
  test.data <- sub.retro.df[
    grepl("pembro +", sub.retro.df$pembro_group),
  ]
  surv.obj <- with(test.data, Surv(survival, survival_event))
  cox.fit <- summary(coxph(surv.obj ~ age_65 + histology_group, data = test.data))
  trend.cox.fit <- summary(coxph(surv.obj ~ trend_age + histology_group, data = test.data))
  km.fit <- survfit(surv.obj ~ age_65, data = test.data)
  med.surv <- ddply(test.data, .(age_65), summarize, median = round(median(survival), 0))
  g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
    annotate(
      "label",
      label = paste(
        "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
        ", P = ", round(cox.fit$coefficients[1, 5], 2),
        "\nP for trend = ", round(trend.cox.fit$coefficients[1, 5], 2),
        sep = ""
      ),
      x = max(test.data$survival) / 1.3, y = 0.9, size = 7
    ) +
    scale_color_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median OS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median OS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_fill_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median OS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median OS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_y_continuous(
      breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
      limits = c(-0.2, 1)
    ) +
    theme_bw() +
    theme(
      text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
      legend.text = element_text(size = 16),
      legend.title = element_blank(),
      legend.spacing.y = unit(0, "pt"),
      legend.position = c(0.35, 0.1),
      legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
    ) +
    labs(x = "Time (days)", y = "Overall survival")
  ggsave(
    paste(
      "4_Survival_analysis/Pembro+chemo_overall_survival_", file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 7, height = 5, limitsize = FALSE
  )

  ### Progression free survival (PFS)

  # pembrolizumab
  test.data <- sub.retro.df[
    grepl("pembrolizumab", sub.retro.df$pembro_group),
  ]
  surv.obj <- with(test.data, Surv(PFS, PFS_event))
  cox.fit <- summary(coxph(surv.obj ~ age_65 + histology_group, data = test.data))
  trend.cox.fit <- summary(coxph(surv.obj ~ trend_age + histology_group, data = test.data))
  km.fit <- survfit(surv.obj ~ age_65, data = test.data)
  med.surv <- ddply(test.data, .(age_65), summarize, median = round(median(PFS), 0))
  g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
    annotate(
      "label",
      label = paste(
        "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
        ", P = ", round(cox.fit$coefficients[1, 5], 2),
        "\nP for trend = ", round(trend.cox.fit$coefficients[1, 5], 2),
        sep = ""
      ),
      x = max(test.data$PFS) / 1.3, y = 0.9, size = 7
    ) +
    scale_color_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median PFS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median PFS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_fill_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median PFS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median PFS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_y_continuous(
      breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
      limits = c(-0.2, 1)
    ) +
    theme_bw() +
    theme(
      text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
      legend.text = element_text(size = 16),
      legend.title = element_blank(),
      legend.spacing.y = unit(0, "pt"),
      legend.position = c(0.35, 0.1),
      legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
    ) +
    labs(x = "Time (days)", y = "Progression-free survival")
  ggsave(
    paste(
      "4_Survival_analysis/Pembro_PFS_", file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 7, height = 5, limitsize = FALSE
  )

  # pembrolizumab + chemotherapy
  test.data <- sub.retro.df[
    grepl("pembro +", sub.retro.df$pembro_group),
  ]
  surv.obj <- with(test.data, Surv(PFS, PFS_event))
  cox.fit <- summary(coxph(surv.obj ~ age_65 + histology_group, data = test.data))
  trend.cox.fit <- summary(coxph(surv.obj ~ trend_age + histology_group, data = test.data))
  km.fit <- survfit(surv.obj ~ age_65, data = test.data)
  med.surv <- ddply(test.data, .(age_65), summarize, median = round(median(PFS), 0))
  g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
    annotate(
      "label",
      label = paste(
        "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
        ", P = ", round(cox.fit$coefficients[1, 5], 2),
        "\nP for trend = ", round(trend.cox.fit$coefficients[1, 5], 2),
        sep = ""
      ),
      x = max(test.data$PFS) / 1.3, y = 0.9, size = 7
    ) +
    scale_color_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median PFS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median PFS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_fill_manual(
      values = c(labcorp.col[1], labcorp.col[3]),
      labels = c(
        paste(
          "<65, N=", table(test.data$age_65)[1],
          ", median PFS=", med.surv$median[1],
          sep = ""
        ),
        bquote({
          "" >= 65
        } ~ .(paste(
          ", N=", table(test.data$age_65)[2],
          ", median PFS=", med.surv$median[2],
          sep = ""
        )))
      )
    ) +
    scale_y_continuous(
      breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
      limits = c(-0.2, 1)
    ) +
    theme_bw() +
    theme(
      text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
      legend.text = element_text(size = 16),
      legend.title = element_blank(),
      legend.spacing.y = unit(0, "pt"),
      legend.position = c(0.35, 0.1),
      legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
    ) +
    labs(x = "Time (days)", y = "Progression-free survival")
  ggsave(
    paste(
      "4_Survival_analysis/Pembro+chemo_PFS_", file.names[i], ".pdf",
      sep = ""
    ), g,
    device = "pdf", width = 7, height = 5, limitsize = FALSE
  )
}

### re-run analysis and plotting for testing males vs females ###

### Overall survival

# pembrolizumab
test.data <- retro.df[
  grepl("pembrolizumab", retro.df$pembro_group),
]
surv.obj <- with(test.data, Surv(survival, survival_event))
cox.fit <- summary(coxph(surv.obj ~ gender + histology_group, data = test.data))
km.fit <- survfit(surv.obj ~ gender, data = test.data)
med.surv <- ddply(test.data, .(gender), summarize, median = round(median(survival), 0))
g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
  annotate(
    "label",
    label = paste(
      "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
      ", P = ", round(cox.fit$coefficients[1, 5], 2),
      sep = ""
    ),
    x = max(test.data$survival) / 1.3, y = 0.9, size = 7
  ) +
  scale_color_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median OS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median OS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_fill_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median OS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median OS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_y_continuous(
    breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
    limits = c(-0.2, 1)
  ) +
  theme_bw() +
  theme(
    text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
    legend.text = element_text(size = 16),
    legend.title = element_blank(),
    legend.spacing.y = unit(0, "pt"),
    legend.position = c(0.35, 0.1),
    legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
  ) +
  labs(x = "Time (days)", y = "Overall survival")
ggsave(
  "4_Survival_analysis/Pembro_overall_survival_males_vs_females.pdf", g,
  device = "pdf", width = 7, height = 5, limitsize = FALSE
)

# pembrolizumab + chemotherapy
test.data <- retro.df[
  grepl("pembro +", retro.df$pembro_group),
]
surv.obj <- with(test.data, Surv(survival, survival_event))
cox.fit <- summary(coxph(surv.obj ~ gender + histology_group, data = test.data))
km.fit <- survfit(surv.obj ~ gender, data = test.data)
med.surv <- ddply(test.data, .(gender), summarize, median = round(median(survival), 0))
g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
  annotate(
    "label",
    label = paste(
      "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
      ", P = ", round(cox.fit$coefficients[1, 5], 2),
      sep = ""
    ),
    x = max(test.data$survival) / 1.3, y = 0.9, size = 7
  ) +
  scale_color_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median OS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median OS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_fill_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median OS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median OS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_y_continuous(
    breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
    limits = c(-0.2, 1)
  ) +
  theme_bw() +
  theme(
    text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
    legend.text = element_text(size = 16),
    legend.title = element_blank(),
    legend.spacing.y = unit(0, "pt"),
    legend.position = c(0.35, 0.1),
    legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
  ) +
  labs(x = "Time (days)", y = "Overall survival")
ggsave(
  "4_Survival_analysis/Pembro+chemo_overall_survival_males_vs_females.pdf", g,
  device = "pdf", width = 7, height = 5, limitsize = FALSE
)

### Progression free survival (PFS)

# pembrolizumab
test.data <- retro.df[
  grepl("pembrolizumab", retro.df$pembro_group),
]
surv.obj <- with(test.data, Surv(PFS, PFS_event))
cox.fit <- summary(coxph(surv.obj ~ gender + histology_group, data = test.data))
km.fit <- survfit(surv.obj ~ gender, data = test.data)
med.surv <- ddply(test.data, .(gender), summarize, median = round(median(PFS), 0))
g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
  annotate(
    "label",
    label = paste(
      "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
      ", P = ", round(cox.fit$coefficients[1, 5], 2),
      sep = ""
    ),
    x = max(test.data$PFS) / 1.3, y = 0.9, size = 7
  ) +
  scale_color_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median PFS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median PFS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_fill_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median PFS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median PFS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_y_continuous(
    breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
    limits = c(-0.2, 1)
  ) +
  theme_bw() +
  theme(
    text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
    legend.text = element_text(size = 16),
    legend.title = element_blank(),
    legend.spacing.y = unit(0, "pt"),
    legend.position = c(0.35, 0.1),
    legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
  ) +
  labs(x = "Time (days)", y = "Progression-free survival")
ggsave(
  "4_Survival_analysis/Pembro_PFS_males_vs_females.pdf", g,
  device = "pdf", width = 7, height = 5, limitsize = FALSE
)

# pembrolizumab + chemotherapy
test.data <- retro.df[
  grepl("pembro +", retro.df$pembro_group),
]
surv.obj <- with(test.data, Surv(PFS, PFS_event))
cox.fit <- summary(coxph(surv.obj ~ gender + histology_group, data = test.data))
km.fit <- survfit(surv.obj ~ gender, data = test.data)
med.surv <- ddply(test.data, .(gender), summarize, median = round(median(PFS), 0))
g <- autoplot(km.fit, conf.int.alpha = 0.1, censor.shape = "") +
  annotate(
    "label",
    label = paste(
      "HR = ", round(1 / cox.fit$coefficients[1, 2], 2),
      ", P = ", round(cox.fit$coefficients[1, 5], 2),
      sep = ""
    ),
    x = max(test.data$PFS) / 1.3, y = 0.9, size = 7
  ) +
  scale_color_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median PFS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median PFS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_fill_manual(
    values = c(labcorp.col[1], labcorp.col[3]),
    labels = c(
      paste(
        "Female, N=", table(test.data$gender)[1],
        ", median PFS=", med.surv$median[1],
        sep = ""
      ),
      paste(
        "Male, N=", table(test.data$gender)[2],
        ", median PFS=", med.surv$median[2],
        sep = ""
      )
    )
  ) +
  scale_y_continuous(
    breaks = seq(0, 1, 0.25), labels = paste(seq(0, 1, 0.25) * 100, "%", sep = ""),
    limits = c(-0.2, 1)
  ) +
  theme_bw() +
  theme(
    text = element_text(size = 24), plot.margin = margin(c(5, 20, 5, 5)),
    legend.text = element_text(size = 16),
    legend.title = element_blank(),
    legend.spacing.y = unit(0, "pt"),
    legend.position = c(0.35, 0.1),
    legend.background = element_rect(linewidth = 0.5, linetype = "solid", color = "black")
  ) +
  labs(x = "Time (days)", y = "Progression-free survival")
ggsave(
  "4_Survival_analysis/Pembro+chemo_PFS_males_vs_females.pdf", g,
  device = "pdf", width = 7, height = 5, limitsize = FALSE
)
```

# R session information

```{r r-session, echo=FALSE}
sessionInfo()
```
