Overview of R analysis for comparing CSC content among cytotoxic drugs across a range of spheroid viability index.

To compare CSC content under chemotherapies, we developed a method for comparing CSC index within a range of spheroid viability index (SVI) by calculating the normalized CSC index’s area under the curve (AUC). Briefly, a range of SVI is defined based on the SVI of all drugs, and then the drug concentrations of the SVIs are interpolated using a non-linear (exponential model fitting) approach. Next, interpolation of the CSC index of each SVI value is performed by linear interpolation between the nearby interpolated drug concentrations. To compare CSC content across a range of SVI, an AUC of the CSC index is calculated for each drug. The CSC index’s AUC is further normalized by the vehicle control. Statistical test is performed, and bar graphs are used for data visualization.

Figure 1: Overview of analysis for CSC content among cytotoxic drugs across a range of SVI.
Figure 1: Overview of analysis for CSC content among cytotoxic drugs across a range of SVI.

1. Analysis overview

Here, the analysis composed of 5 main sections below.

  1. Section 1: Define information of the dataset.
  2. Section 2: Load input data.
  3. Section 3: Create analysis pipeline.
    • Part 3.1: Find SVIs of all drugs.
      3.1.1 Find maximum and minimum SVI of each drug.
      3.1.2 Define maximum and minimum of SVI across all drugs.
      3.1.3 Define the range of SVI for AUC of the CSC index calculation.
    • Part 3.2: Calculate drug concentration of each desired SVI by interpolation.
    • Part 3.3: Calculate the CSC index for each drug concentration by interpolating from the interpolated drug concentrations.
      3.3.1 Find nearest low/high drug concentration and CSC index from the interpolated drug concentration.
      3.3.2 Interpolate CSC index from interpolated drug concentration.
    • Part 3.4: Reconsider SVI range, according to NA value possibly present.
      3.4.1 Check whether NA present in the data.
      3.4.2 Exclude SVI that contain NA values and define selected SVI range.
    • Part 3.5: Find AUC of CSC index across the selected SVI range.
      3.5.1 Calculate AUC of CSC index for vehicle control.
      3.5.2 Calculate normalized CSC index’s AUC of each drug.
    • Part 3.6: Create summary analysis.
  4. Section 4: Statistical test
    • Part 4.1: Normality test
    • Part 4.2: Statistical test
  5. Section 5: Data visualization

2. Inputs

The CSC index of each drug was created from the file name DrugX_Input_forCSCindexAUC.csv from “Evaluating CSC content and cytotoxicity under anti-cancer drug treatments for the 3D multi-spheroid model using 3D-SiSP analytical method.” which will be used as input data for this analysis.

To compare the CSC index of cytotoxic drugs across a range of spheroid viability index (SVI), we used drug A and drug B as examples.

In the DrugX_Input_forCSCindexAUC.csv file contains 10 columns, which are described as below.

  1. Drug = Name of the drug
  2. Concentration_uM = Concentration of the drug (μM)
  3. SVI = Spheroid viability index
  4. CSCindex = Cancer stem cell index

Here, we provided a set of example inputs which contained A_Input_forCSCindexAUC.csv, B_Input_forCSCindexAUC.csv for drug A and drug B, respectively.

Figure 2: Double y-axis graphs show spheroid viability index (SVI) and CSC index of drug A (left) and drug B(right)./ Figure 2: Double y-axis graphs show spheroid viability index (SVI) and CSC index of drug A (left) and drug B(right).

Analysis for Comparing CSC content among cytotoxic drugs across a range of spheroid viability index.

Import R library

library(dplyr)
library(ggplot2)
library(nlme)  # For non-linear regression
library(pracma) # For AUC calculation by trapezoidal rule
library(viridis) # For color library
library(ggpubr) # For statistical test

Section 1: Define information of the dataset.

To define information of the dataset.

1.1 Define working directory: Output_Directory
1.2 Define input directory: Input_Directory

# Dataset example: drug A and drug B 
  ## Output directory
    Output_Directory  <- 'path/to/directory'
    setwd(Output_Directory)
  
  ## Input directory
    Input_Directory   <- 'path/to/directory'

Section 2: Load the input data.

    FileNames <- list.files(Input_Directory)  # Get a list of .csv files in the input directory
    FileNames <- as.list(FileNames) # Make .csv files as a list

Import two .csv files for 2 drugs and then calculate the required variable for further analysis.

# Create a blank list to store `Experimental_drug` information.
  Experimental_list <- list()

# Calculate the required variable for all drugs for further analysis.
for (Drug_FileName in FileNames){
    # Import each `.csv` file.
      Drug_FilePath       <- file.path(Input_Directory, Drug_FileName)
      Experimental_DrugX  <- read.csv(Drug_FilePath)
      
      ## Change all columns to numeric except the`Drug` column.
        Experimental_DrugX[, -1] <- apply(Experimental_DrugX[, -1], 
                                          2, 
                                          as.numeric
                                          ) 
        Experimental_DrugX
  
    # Rename the data frame to show the drug name.
      ## Extract the drug name.
        Drug_Name <- sub("_.*", "", Drug_FileName)
      
      ## Rename the data frame.
        Experimental_Data <- assign(paste0("Experimental_Drug", Drug_Name), 
                                      Experimental_DrugX
                                    ) 
      
    # Store the data frame into the list `Experimental_list`.
      Experimental_list[[length(Experimental_list)+1]] <- Experimental_Data 
  }

Observe the Experimental_Drug data

# The list which shows information of all drugs.
head(Experimental_list)
## [[1]]
##    Drug Concentration_pM log10_Concentration_pM       SVI  CSCindex Replicate
## 1     A            1e+06                      6 0.5266515 1.1670821         1
## 2     A            1e+06                      6 0.3727367 1.1439455         2
## 3     A            1e+06                      6 0.3128734 1.1833153         3
## 4     A            1e+05                      5 0.4753377 1.2614324         1
## 5     A            1e+05                      5 0.2924306 1.3646002         2
## 6     A            1e+05                      5 0.2619729 1.1668776         3
## 7     A            1e+04                      4 0.7616551 1.6280216         1
## 8     A            1e+04                      4 0.5151447 1.3951609         2
## 9     A            1e+04                      4 0.5343289 1.3931141         3
## 10    A            1e+03                      3 1.0047226 0.9452869         1
## 11    A            1e+03                      3 1.0996911 1.0053784         2
## 12    A            1e+03                      3 0.7377690 0.9074044         3
## 13    A            0e+00                      0 0.8029457 0.9476974         1
## 14    A            0e+00                      0 1.1784421 1.0611647         2
## 15    A            0e+00                      0 1.0186123 0.9911379         3
## 
## [[2]]
##    Drug Concentration_pM log10_Concentration_pM       SVI  CSCindex Replicate
## 1     B            5e+07                    7.7 0.4828559 0.9296289         1
## 2     B            5e+07                    7.7 0.4610764 0.8759742         2
## 3     B            5e+07                    7.7 0.3978878 0.7660433         3
## 4     B            5e+06                    6.7 0.6813254 1.3671360         1
## 5     B            5e+06                    6.7 0.6765575 1.3230907         2
## 6     B            5e+06                    6.7 0.5448808 1.2561047         3
## 7     B            5e+05                    5.7 0.5034974 1.4586134         1
## 8     B            5e+05                    5.7 0.7315248 1.4095987         2
## 9     B            5e+05                    5.7 0.7530513 1.4797003         3
## 10    B            5e+04                    4.7 0.8363375 1.7513541         1
## 11    B            5e+04                    4.7 0.9671786 1.8060602         2
## 12    B            5e+04                    4.7 0.8248147 1.4299233         3
## 13    B            0e+00                    0.0 1.0640481 1.0678026         1
## 14    B            0e+00                    0.0 1.0720928 0.9787869         2
## 15    B            0e+00                    0.0 0.8638591 0.9534105         3
# Drug A
head(Experimental_DrugA)
##   Drug Concentration_pM log10_Concentration_pM       SVI CSCindex Replicate
## 1    A            1e+06                      6 0.5266515 1.167082         1
## 2    A            1e+06                      6 0.3727367 1.143946         2
## 3    A            1e+06                      6 0.3128734 1.183315         3
## 4    A            1e+05                      5 0.4753377 1.261432         1
## 5    A            1e+05                      5 0.2924306 1.364600         2
## 6    A            1e+05                      5 0.2619729 1.166878         3
# Drug B
head(Experimental_DrugB)
##   Drug Concentration_pM log10_Concentration_pM       SVI  CSCindex Replicate
## 1    B            5e+07                    7.7 0.4828559 0.9296289         1
## 2    B            5e+07                    7.7 0.4610764 0.8759742         2
## 3    B            5e+07                    7.7 0.3978878 0.7660433         3
## 4    B            5e+06                    6.7 0.6813254 1.3671360         1
## 5    B            5e+06                    6.7 0.6765575 1.3230907         2
## 6    B            5e+06                    6.7 0.5448808 1.2561047         3

Section 3: Create analysis pipeline.

Part 3.1: Find SVI range for all drugs.

3.1.1 Find minimum SVI of each drug.

# Create a blank data frame to store `DrugX_minSVI` from the highest concentration of each drug.
Data_minSVI <- data.frame()

# Create a for loop to calculate the lowest SVI from the highest concentration of each drug.
for (Experimental_DrugX in Experimental_list){
  
  # Find the highest concentration of the drug.
    DrugX_MaxConc <- max(Experimental_DrugX$Concentration_pM) 
    
  # Filter only SVI of the highest drug concentration.
    DrugX_minSVI <- Experimental_DrugX %>%
                      dplyr::filter(Concentration_pM == DrugX_MaxConc) %>%
                      select(Drug, SVI)
    
    Data_minSVI <- rbind(Data_minSVI, 
                          DrugX_minSVI
                         )
  }

# Show the SVIs from the highest concentration of each drug.
head(Data_minSVI)
##   Drug       SVI
## 1    A 0.5266515
## 2    A 0.3727367
## 3    A 0.3128734
## 4    B 0.4828559
## 5    B 0.4610764
## 6    B 0.3978878

3.1.2 Define maximum and minimum of SVI for all drugs.

Maximum SVI will be set to 1 which is the vehicle control.

# Define maximum of SVI.
  HighestSVI_LastPoint <- 1

  print(paste0("The last point (highest SVI) of the AUC range across all drugs is ", HighestSVI_LastPoint))
## [1] "The last point (highest SVI) of the AUC range across all drugs is 1"

Minimum SVI will be determined by the highest value among the minimum SVIs across all drugs, to further analyze the CSC index within the same range of SVI.”

# Find the lowest of SVI across all drugs.
  minSVI <- max(Data_minSVI$SVI)
  print(paste0("Minimum SVI of across all drugs is ", minSVI))
## [1] "Minimum SVI of across all drugs is 0.526651533159554"
  Rounded_minSVI <- round(minSVI, digits = 2)
  LowestSVI_1stPoint <- ceiling(Rounded_minSVI / 0.05) * 0.05
  
  print(paste0("The 1st point (lowest SVI) of the AUC range across all drugs is ", LowestSVI_1stPoint))
## [1] "The 1st point (lowest SVI) of the AUC range across all drugs is 0.55"

3.1.3 Define the range of SVI to calculate AUC of the CSC index.

# Summarize the range of SVI.
  SVI_Range <- c(HighestSVI_LastPoint, 
                  LowestSVI_1stPoint
                 )
  print(paste("The SVI range for calculating the AUC of the CSC index is between", HighestSVI_LastPoint, "and", LowestSVI_1stPoint))
## [1] "The SVI range for calculating the AUC of the CSC index is between 1 and 0.55"
# Define the SVI values between the SVI range with an increment of 0.05.
  Desired_SVIvalues <- seq(SVI_Range[1], 
                             SVI_Range[2], 
                             by = -0.05
                           )
  print(paste("Based on the SVI range, the AUC of the CSC index will be calculated within this range. Therefore, CSC index will be calculated at SVI values of", paste(Desired_SVIvalues, collapse = ", ")))
## [1] "Based on the SVI range, the AUC of the CSC index will be calculated within this range. Therefore, CSC index will be calculated at SVI values of 1, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55"

Part 3.2: Calculate drug concentration of each desired SVI by interpolation.

# Create a blank list to store `InterpolatedConc_DrugX` information.
  InterpolatedConc_list <- list()

# Find drug concentration of each desired SVI.
for (Experimental_DrugX in Experimental_list){

    DrugX_FindConc <- dplyr::select(Experimental_DrugX, 
                                      Drug, 
                                      log10_Concentration_pM, 
                                      SVI
                                    )
  
    # Define a nonlinear model (exponential decay).
      Model_DrugX <- nls(SVI ~ exp(a + b * log10_Concentration_pM),
                          data = DrugX_FindConc,
                          start = list(a = 0, b = 0)
                         )  
        
    # Define a function to find `log10_Concentration_pM` form a given SVI (`SVI`).
      find.DrugX.log10Conc.pM <- function(SVI) 
        {
          uniroot(
            function(log10_Concentration) 
              {
              predict(Model_DrugX, 
                      newdata = data.frame(log10_Concentration_pM = log10_Concentration)) - SVI
              },
            interval = range(DrugX_FindConc$log10_Concentration_pM),
            extendInt = "yes"
          )$root
        }
    
    # Predict `log10_Concentration_pM` from each SVI (`SVI`).
      Desired_SVIvalues
      Predicted_DrugX_log10_Conc_pM <- sapply(Desired_SVIvalues, 
                                              find.DrugX.log10Conc.pM)
    
    # Summarize the interpolated output.
      InterpolatedConc_DrugX <- data.frame(Drug = DrugX_FindConc$Drug[1],
                                            SVI = Desired_SVIvalues,
                                            log10_Concentration_pM = Predicted_DrugX_log10_Conc_pM,
                                            Concentration_pM = 10^(Predicted_DrugX_log10_Conc_pM)
                                          )
    
      InterpolatedConc_DrugX
    
    # Rename the data frame to show the drug name.
      ## Extract the drug name.
      Drug_Name <- InterpolatedConc_DrugX$Drug[[1]]
      
      ## Rename the data frame 
      InterpolatedConc_DrugX_Data <- assign(paste0("InterpolatedConc_Drug", Drug_Name), 
                                              InterpolatedConc_DrugX
                                            ) 
      
    # Store the data frame into the list `InterpolatedConc_list`
      InterpolatedConc_list[[length(InterpolatedConc_list)+1]] <- InterpolatedConc_DrugX_Data
    
  }

Observe the InterpolatedConc_Drug data.

# The list which shows information of all drugs.
head(InterpolatedConc_list)
## [[1]]
##    Drug  SVI log10_Concentration_pM Concentration_pM
## 1     A 1.00              0.4658773         2.923326
## 2     A 0.95              0.8163205         6.551195
## 3     A 0.90              1.1856657        15.334361
## 4     A 0.85              1.5761514        37.683516
## 5     A 0.80              1.9903186        97.795429
## 6     A 0.75              2.4312231       269.912538
## 7     A 0.70              2.9025564       799.017714
## 8     A 0.65              3.4088326      2563.495571
## 9     A 0.60              3.9556517      9029.249693
## 10    A 0.55              4.5500784     35487.746764
## 
## [[2]]
##    Drug  SVI log10_Concentration_pM Concentration_pM
## 1     B 1.00              0.5229577     3.333939e+00
## 2     B 0.95              1.1844042     1.528988e+01
## 3     B 0.90              1.8816524     7.614694e+01
## 4     B 0.85              2.6187342     4.156562e+02
## 5     B 0.80              3.4005238     2.514918e+03
## 6     B 0.75              4.2327854     1.709171e+04
## 7     B 0.70              5.1224883     1.325832e+05
## 8     B 0.65              6.0781535     1.197164e+06
## 9     B 0.60              7.1103569     1.289309e+07
## 10    B 0.55              8.2324125     1.707704e+08
# DrugA
head(InterpolatedConc_DrugA)
##   Drug  SVI log10_Concentration_pM Concentration_pM
## 1    A 1.00              0.4658773         2.923326
## 2    A 0.95              0.8163205         6.551195
## 3    A 0.90              1.1856657        15.334361
## 4    A 0.85              1.5761514        37.683516
## 5    A 0.80              1.9903186        97.795429
## 6    A 0.75              2.4312231       269.912538
# DrugB
head(InterpolatedConc_DrugB)
##   Drug  SVI log10_Concentration_pM Concentration_pM
## 1    B 1.00              0.5229577         3.333939
## 2    B 0.95              1.1844042        15.289883
## 3    B 0.90              1.8816524        76.146938
## 4    B 0.85              2.6187342       415.656151
## 5    B 0.80              3.4005238      2514.917842
## 6    B 0.75              4.2327854     17091.705307

Part 3.3: Calculate the CSC index for each drug concentration by interpolating from the interpolated drug concentrations.

3.3.1 Find nearest low/high drug concentration and CSC index from the interpolated drug concentration.

# Create a blank list to store `NearestData_DrugX` information.
  NearestData_list <- list()

for (InterpolatedConc_DrugX in InterpolatedConc_list){
  
  # Extract the interpolated drug concentration.
   DrugX_Conc <- InterpolatedConc_DrugX$Concentration_pM %>% 
                  as.list()
  
  # Extract the drug concentration which were used in wet lab experiment from `Experimental_list`.
    ## Extract the drug name from `InterpolatedConc_DrugX`
      Drug_Name <- InterpolatedConc_DrugX$Drug[1]
    
    ## Iterate over the list of `Experimental_list` and select the data frame which the drug name matchs with `InterpolatedConc_DrugX`.
      Experimental_DrugX <- do.call(rbind, 
                                      lapply(Experimental_list, 
                                              function(df) df[df$Drug == Drug_Name, ]))
      
    ## Sort the drug concentrations from `Experimental_DrugX` in ascending order.
      Sorted_Conc <- sort(Experimental_DrugX$Concentration_pM)
  
  # Create a blank list to store `NearestData_DrugX` and `CSCindex` information.
    NearestData_DrugX <- data.frame() 
  
    for (Conc in DrugX_Conc){
      
      # Find the nearest low and high concentrations.
      NearestConc_Low   <- max(Sorted_Conc[Sorted_Conc <= Conc])
      NearestConc_High  <- min(Sorted_Conc[Sorted_Conc >= Conc])
      
      # Find `CSCindex` from the nearest low and high concentrations.
        ## The nearest low concentration
        CSCindex_NearestLow <- Experimental_DrugX %>%
                                      filter(Concentration_pM == NearestConc_Low) %>% 
                                      select(CSCindex) %>% 
                                      t %>% 
                                      as.vector() 
        CSCindex_NearestLow
      
        ## The nearest high concentration
        CSCindex_NearestHigh <- Experimental_DrugX %>% filter(Concentration_pM == NearestConc_High) %>% 
                                      select(CSCindex) %>% 
                                      t %>% 
                                      as.vector() 
        CSCindex_NearestHigh
      
      NearestValues_DrugX <- c(Experimental_DrugX$Drug[1], Conc, 
                                NearestConc_Low, CSCindex_NearestLow,
                                NearestConc_High, CSCindex_NearestHigh
                               )
      
      NearestData_DrugX <- rbind(NearestData_DrugX, 
                                  NearestValues_DrugX
                                 )
      
      }
    
  # Rename columns.
    colnames(NearestData_DrugX) <- c("Drug", "Concentration_pM", 
                                
                                "Nearest_Low_Concentration_pM", 
                                "CSCindex_Low_r1", "CSCindex_Low_r2", "CSCindex_Low_r3",
                                
                                "Nearest_High_Concentration_pM", 
                                "CSCindex_High_r1", "CSCindex_High_r2", "CSCindex_High_r3")
  
  # Attach the SVI values to the `NearestData_DrugX`.
    NearestData_DrugX <- merge(NearestData_DrugX, 
                                 InterpolatedConc_DrugX, 
                                 by = c("Drug", "Concentration_pM"), 
                                 all = FALSE
                               )
  
  # Reorder columns.
    NearestData_DrugX <- NearestData_DrugX %>% 
                            select(Drug,
                                     SVI, 
                                     Concentration_pM, 
                                     log10_Concentration_pM, 
                                     everything()
                                   )
    
  # Sort the nearest values according to SVI.
    NearestData_DrugX <- NearestData_DrugX[order(NearestData_DrugX$SVI), ]
  
  # Change the values to numeric.
    NearestData_DrugX[, -1] <- lapply(NearestData_DrugX[, -1], as.numeric)

  # Rename the data frame to show the drug name.
    ## Extract the drug name.
      Drug_Name <- InterpolatedConc_DrugX$Drug[1]
    
    ## Rename the data frame.
      NearestData_DrugX_Data <- assign(paste0("NearestData_Drug", Drug_Name), 
                                       NearestData_DrugX
                                       ) 
      
  # Store the data frame into the list `NearestData_list`.
    NearestData_list[[length(NearestData_list)+1]] <- NearestData_DrugX_Data
  }
## Warning in min(Sorted_Conc[Sorted_Conc >= Conc]): no non-missing arguments to
## min; returning Inf
## Warning in rbind(deparse.level, ...): number of columns of result, 10, is not a
## multiple of vector length 7 of arg 2
## Warning in lapply(NearestData_DrugX[, -1], as.numeric): NAs introduced by
## coercion

Observe the NearestData_Drug data.

# The list which shows information of all drugs.
head(NearestData_list)
## [[1]]
##    Drug  SVI Concentration_pM log10_Concentration_pM
## 5     A 0.55     35487.746764              4.5500784
## 9     A 0.60      9029.249693              3.9556517
## 3     A 0.65      2563.495571              3.4088326
## 8     A 0.70       799.017714              2.9025564
## 4     A 0.75       269.912538              2.4312231
## 10    A 0.80        97.795429              1.9903186
## 6     A 0.85        37.683516              1.5761514
## 1     A 0.90        15.334361              1.1856657
## 7     A 0.95         6.551195              0.8163205
## 2     A 1.00         2.923326              0.4658773
##    Nearest_Low_Concentration_pM CSCindex_Low_r1 CSCindex_Low_r2 CSCindex_Low_r3
## 5                         10000       1.6280216        1.395161       1.3931141
## 9                          1000       0.9452869        1.005378       0.9074044
## 3                          1000       0.9452869        1.005378       0.9074044
## 8                             0       0.9476974        1.061165       0.9911379
## 4                             0       0.9476974        1.061165       0.9911379
## 10                            0       0.9476974        1.061165       0.9911379
## 6                             0       0.9476974        1.061165       0.9911379
## 1                             0       0.9476974        1.061165       0.9911379
## 7                             0       0.9476974        1.061165       0.9911379
## 2                             0       0.9476974        1.061165       0.9911379
##    Nearest_High_Concentration_pM CSCindex_High_r1 CSCindex_High_r2
## 5                          1e+05        1.2614324         1.364600
## 9                          1e+04        1.6280216         1.395161
## 3                          1e+04        1.6280216         1.395161
## 8                          1e+03        0.9452869         1.005378
## 4                          1e+03        0.9452869         1.005378
## 10                         1e+03        0.9452869         1.005378
## 6                          1e+03        0.9452869         1.005378
## 1                          1e+03        0.9452869         1.005378
## 7                          1e+03        0.9452869         1.005378
## 2                          1e+03        0.9452869         1.005378
##    CSCindex_High_r3
## 5         1.1668776
## 9         1.3931141
## 3         1.3931141
## 8         0.9074044
## 4         0.9074044
## 10        0.9074044
## 6         0.9074044
## 1         0.9074044
## 7         0.9074044
## 2         0.9074044
## 
## [[2]]
##    Drug  SVI Concentration_pM log10_Concentration_pM
## 5     B 0.55     1.707704e+08              8.2324125
## 2     B 0.60     1.289309e+07              7.1103569
## 1     B 0.65     1.197164e+06              6.0781535
## 3     B 0.70     1.325832e+05              5.1224883
## 6     B 0.75     1.709171e+04              4.2327854
## 7     B 0.80     2.514918e+03              3.4005238
## 9     B 0.85     4.156562e+02              2.6187342
## 10    B 0.90     7.614694e+01              1.8816524
## 4     B 0.95     1.528988e+01              1.1844042
## 8     B 1.00     3.333939e+00              0.5229577
##    Nearest_Low_Concentration_pM CSCindex_Low_r1 CSCindex_Low_r2 CSCindex_Low_r3
## 5                         5e+07       0.9296289       0.8759742       0.7660433
## 2                         5e+06       1.3671360       1.3230907       1.2561047
## 1                         5e+05       1.4586134       1.4095987       1.4797003
## 3                         5e+04       1.7513541       1.8060602       1.4299233
## 6                         0e+00       1.0678026       0.9787869       0.9534105
## 7                         0e+00       1.0678026       0.9787869       0.9534105
## 9                         0e+00       1.0678026       0.9787869       0.9534105
## 10                        0e+00       1.0678026       0.9787869       0.9534105
## 4                         0e+00       1.0678026       0.9787869       0.9534105
## 8                         0e+00       1.0678026       0.9787869       0.9534105
##    Nearest_High_Concentration_pM CSCindex_High_r1 CSCindex_High_r2
## 5                            Inf               NA     1.707704e+08
## 2                          5e+07        0.9296289     8.759742e-01
## 1                          5e+06        1.3671360     1.323091e+00
## 3                          5e+05        1.4586134     1.409599e+00
## 6                          5e+04        1.7513541     1.806060e+00
## 7                          5e+04        1.7513541     1.806060e+00
## 9                          5e+04        1.7513541     1.806060e+00
## 10                         5e+04        1.7513541     1.806060e+00
## 4                          5e+04        1.7513541     1.806060e+00
## 8                          5e+04        1.7513541     1.806060e+00
##    CSCindex_High_r3
## 5      5.000000e+07
## 2      7.660433e-01
## 1      1.256105e+00
## 3      1.479700e+00
## 6      1.429923e+00
## 7      1.429923e+00
## 9      1.429923e+00
## 10     1.429923e+00
## 4      1.429923e+00
## 8      1.429923e+00
# Drug A
head(NearestData_DrugA)
##    Drug  SVI Concentration_pM log10_Concentration_pM
## 5     A 0.55      35487.74676               4.550078
## 9     A 0.60       9029.24969               3.955652
## 3     A 0.65       2563.49557               3.408833
## 8     A 0.70        799.01771               2.902556
## 4     A 0.75        269.91254               2.431223
## 10    A 0.80         97.79543               1.990319
##    Nearest_Low_Concentration_pM CSCindex_Low_r1 CSCindex_Low_r2 CSCindex_Low_r3
## 5                         10000       1.6280216        1.395161       1.3931141
## 9                          1000       0.9452869        1.005378       0.9074044
## 3                          1000       0.9452869        1.005378       0.9074044
## 8                             0       0.9476974        1.061165       0.9911379
## 4                             0       0.9476974        1.061165       0.9911379
## 10                            0       0.9476974        1.061165       0.9911379
##    Nearest_High_Concentration_pM CSCindex_High_r1 CSCindex_High_r2
## 5                          1e+05        1.2614324         1.364600
## 9                          1e+04        1.6280216         1.395161
## 3                          1e+04        1.6280216         1.395161
## 8                          1e+03        0.9452869         1.005378
## 4                          1e+03        0.9452869         1.005378
## 10                         1e+03        0.9452869         1.005378
##    CSCindex_High_r3
## 5         1.1668776
## 9         1.3931141
## 3         1.3931141
## 8         0.9074044
## 4         0.9074044
## 10        0.9074044
# Drug B
head(NearestData_DrugB)
##   Drug  SVI Concentration_pM log10_Concentration_pM
## 5    B 0.55     1.707704e+08               8.232412
## 2    B 0.60     1.289309e+07               7.110357
## 1    B 0.65     1.197164e+06               6.078153
## 3    B 0.70     1.325832e+05               5.122488
## 6    B 0.75     1.709171e+04               4.232785
## 7    B 0.80     2.514918e+03               3.400524
##   Nearest_Low_Concentration_pM CSCindex_Low_r1 CSCindex_Low_r2 CSCindex_Low_r3
## 5                        5e+07       0.9296289       0.8759742       0.7660433
## 2                        5e+06       1.3671360       1.3230907       1.2561047
## 1                        5e+05       1.4586134       1.4095987       1.4797003
## 3                        5e+04       1.7513541       1.8060602       1.4299233
## 6                        0e+00       1.0678026       0.9787869       0.9534105
## 7                        0e+00       1.0678026       0.9787869       0.9534105
##   Nearest_High_Concentration_pM CSCindex_High_r1 CSCindex_High_r2
## 5                           Inf               NA     1.707704e+08
## 2                         5e+07        0.9296289     8.759742e-01
## 1                         5e+06        1.3671360     1.323091e+00
## 3                         5e+05        1.4586134     1.409599e+00
## 6                         5e+04        1.7513541     1.806060e+00
## 7                         5e+04        1.7513541     1.806060e+00
##   CSCindex_High_r3
## 5     5.000000e+07
## 2     7.660433e-01
## 1     1.256105e+00
## 3     1.479700e+00
## 6     1.429923e+00
## 7     1.429923e+00

3.3.2 Interpolate CSC index from the interpolated drug concentration.

Create function to interpolate CSC index from the interpolated drug concentration.
Interpolate.CSCindex <- function(NearestData_DrugX)
  {
  # Change SVI to a list.  
    SVI <- as.list(NearestData_DrugX$SVI)
  
  # Create a blank data frame to store `Result` information from 3 replicates.
    Result_df <- data.frame() 
  
  # Calculate the required information (`NearestData`) for each SVI
    for (i in SVI){
    
    # Filter to use an SVI at each iteration of the loop.
      df <- dplyr::filter(NearestData_DrugX, SVI == i)
    
    # Define the drug name
      Drug_Name <- NearestData_DrugX$Drug[1]
    
    ## Replicate 1---------------------------------------------
      # Calculate the slope.
        m1 <- (df$CSCindex_High_r1 - df$CSCindex_Low_r1) / (df$Nearest_High_Concentration_pM - df$Nearest_Low_Concentration_pM)
      
      # Perform linear interpolation to find the interpolated y-value (`Interpolated_CSCindex`).
        log10_Dose_Finding <- df$log10_Concentration_pM
        Dose_Finding <- df$Concentration_pM
        y1 <- df$CSCindex_Low_r1 + m1 * (Dose_Finding - df$Nearest_Low_Concentration_pM)
      
        Rep1_Result <- c(NearestData_DrugX$Drug[1], 
                           i, 
                           Dose_Finding, 
                           log10_Dose_Finding, 
                           m1, 
                           y1, 
                           "1"
                         ) 
        
      # Store the information in `Result_df` data frame
        Result_df <- rbind(Result_df, 
                            Rep1_Result
                           )
    
    ## Replicate 2---------------------------------------------
      # Calculate the slope.
        m2 <- (df$CSCindex_High_r2 - df$CSCindex_Low_r2) / (df$Nearest_High_Concentration_pM - df$Nearest_Low_Concentration_pM)
      
      # Perform linear interpolation to find the interpolated y-value (`Interpolated_CSCindex`).
        y2 <- df$CSCindex_Low_r2 + m2 * (Dose_Finding - df$Nearest_Low_Concentration_pM)
        
        Rep2_Result <- c(NearestData_DrugX$Drug[1], 
                           i, 
                           Dose_Finding, 
                           log10_Dose_Finding, 
                           m2, 
                           y2, 
                           "2"
                         ) 
      
      # Store the information in `Result_df` data frame
        Result_df <- rbind(Result_df, 
                            Rep2_Result
                           )
    
    ## Replicate 3---------------------------------------------
      # Calculate the slope.
        m3 <- (df$CSCindex_High_r3 - df$CSCindex_Low_r3) / (df$Nearest_High_Concentration_pM - df$Nearest_Low_Concentration_pM)
      
      # Perform linear interpolation to find the interpolated y-value (`Interpolated_CSCindex`).
        y3 <- df$CSCindex_Low_r3 + m1 * (Dose_Finding - df$Nearest_Low_Concentration_pM)
      
        Rep3_Result <- c(NearestData_DrugX$Drug[1], i, Dose_Finding, log10_Dose_Finding, m3, y3, "3") 
      
      # Store the information in `Result_df` data frame
       Result_df <- rbind(Result_df,
                            Rep3_Result
                          )
  }
  
    colnames(Result_df) <- c("Drug", 
                               "SVI", 
                               "Concentration_pM", 
                               "log10_Concentration_pM", 
                               "m_Slope", 
                               "Interpolated_CSCindex", 
                               "Replicate"
                             )
    
    # Change the values to numeric
    Result_df[, -1] <- lapply(Result_df[, -1], 
                                as.numeric
                              )
    
    print(Result_df) 
    
    # Write the `Result_df` data into a `.csv` file. 
      write.csv(Result_df, 
                  paste0(Drug_Name, "_Raw_InterpolatedData.csv"), row.names = FALSE)
    
    return(Result_df)
  }
Interpolate CSC indexes.
# Create a blank list to store `CSCindex` information
  CSCindex_list <- list()

# Interpolate CSC indexes.
for (NearestData_DrugX in NearestData_list){
  
  # Interpolate CSC indexes by the created function.
      CSCindex_DrugX <- Interpolate.CSCindex(NearestData_DrugX)
      CSCindex_DrugX
  
  # Rename the data frame to show the drug name.
    ## Extract the drug name.
      Drug_Name <- CSCindex_DrugX$Drug[1]
    
    ## Rename the data frame. 
      CSCindex_DrugX_Data <- assign(paste0("CSCindex_Drug", Drug_Name), 
                                      CSCindex_DrugX
                                    ) 
    
  # Store the data frame into the list `CSCindex_list`.
    CSCindex_list[[length(CSCindex_list)+1]] <- CSCindex_DrugX_Data
  }
##    Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1     A 0.55     35487.746764              4.5500784 -4.073213e-06
## 2     A 0.55     35487.746764              4.5500784 -3.395635e-07
## 3     A 0.55     35487.746764              4.5500784 -2.513739e-06
## 4     A 0.60      9029.249693              3.9556517  7.585941e-05
## 5     A 0.60      9029.249693              3.9556517  4.330917e-05
## 6     A 0.60      9029.249693              3.9556517  5.396774e-05
## 7     A 0.65      2563.495571              3.4088326  7.585941e-05
## 8     A 0.65      2563.495571              3.4088326  4.330917e-05
## 9     A 0.65      2563.495571              3.4088326  5.396774e-05
## 10    A 0.70       799.017714              2.9025564 -2.410455e-06
## 11    A 0.70       799.017714              2.9025564 -5.578633e-05
## 12    A 0.70       799.017714              2.9025564 -8.373344e-05
## 13    A 0.75       269.912538              2.4312231 -2.410455e-06
## 14    A 0.75       269.912538              2.4312231 -5.578633e-05
## 15    A 0.75       269.912538              2.4312231 -8.373344e-05
## 16    A 0.80        97.795429              1.9903186 -2.410455e-06
## 17    A 0.80        97.795429              1.9903186 -5.578633e-05
## 18    A 0.80        97.795429              1.9903186 -8.373344e-05
## 19    A 0.85        37.683516              1.5761514 -2.410455e-06
## 20    A 0.85        37.683516              1.5761514 -5.578633e-05
## 21    A 0.85        37.683516              1.5761514 -8.373344e-05
## 22    A 0.90        15.334361              1.1856657 -2.410455e-06
## 23    A 0.90        15.334361              1.1856657 -5.578633e-05
## 24    A 0.90        15.334361              1.1856657 -8.373344e-05
## 25    A 0.95         6.551195              0.8163205 -2.410455e-06
## 26    A 0.95         6.551195              0.8163205 -5.578633e-05
## 27    A 0.95         6.551195              0.8163205 -8.373344e-05
## 28    A 1.00         2.923326              0.4658773 -2.410455e-06
## 29    A 1.00         2.923326              0.4658773 -5.578633e-05
## 30    A 1.00         2.923326              0.4658773 -8.373344e-05
##    Interpolated_CSCindex Replicate
## 1              1.5242046         1
## 2              1.3865062         2
## 3              1.2892970         3
## 4              1.5543811         1
## 5              1.3531186         2
## 6              1.5164986         3
## 7              1.0638928         1
## 8              1.0730921         2
## 9              1.0260103         3
## 10             0.9457714         1
## 11             1.0165905         2
## 12             0.9892119         3
## 13             0.9470468         1
## 14             1.0461073         2
## 15             0.9904873         3
## 16             0.9474617         1
## 17             1.0557091         2
## 18             0.9909021         3
## 19             0.9476066         1
## 20             1.0590625         2
## 21             0.9910470         3
## 22             0.9476604         1
## 23             1.0603093         2
## 24             0.9911009         3
## 25             0.9476816         1
## 26             1.0607993         2
## 27             0.9911221         3
## 28             0.9476903         1
## 29             1.0610016         2
## 30             0.9911308         3
##    Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1     B 0.55     1.707704e+08              8.2324125            NA
## 2     B 0.55     1.707704e+08              8.2324125  0.000000e+00
## 3     B 0.55     1.707704e+08              8.2324125  0.000000e+00
## 4     B 0.60     1.289309e+07              7.1103569 -9.722378e-09
## 5     B 0.60     1.289309e+07              7.1103569 -9.935922e-09
## 6     B 0.60     1.289309e+07              7.1103569 -1.089025e-08
## 7     B 0.65     1.197164e+06              6.0781535 -2.032832e-08
## 8     B 0.65     1.197164e+06              6.0781535 -1.922399e-08
## 9     B 0.65     1.197164e+06              6.0781535 -4.968792e-08
## 10    B 0.70     1.325832e+05              5.1224883 -6.505348e-07
## 11    B 0.70     1.325832e+05              5.1224883 -8.810255e-07
## 12    B 0.70     1.325832e+05              5.1224883  1.106154e-07
## 13    B 0.75     1.709171e+04              4.2327854  1.367103e-05
## 14    B 0.75     1.709171e+04              4.2327854  1.654546e-05
## 15    B 0.75     1.709171e+04              4.2327854  9.530258e-06
## 16    B 0.80     2.514918e+03              3.4005238  1.367103e-05
## 17    B 0.80     2.514918e+03              3.4005238  1.654546e-05
## 18    B 0.80     2.514918e+03              3.4005238  9.530258e-06
## 19    B 0.85     4.156562e+02              2.6187342  1.367103e-05
## 20    B 0.85     4.156562e+02              2.6187342  1.654546e-05
## 21    B 0.85     4.156562e+02              2.6187342  9.530258e-06
## 22    B 0.90     7.614694e+01              1.8816524  1.367103e-05
## 23    B 0.90     7.614694e+01              1.8816524  1.654546e-05
## 24    B 0.90     7.614694e+01              1.8816524  9.530258e-06
## 25    B 0.95     1.528988e+01              1.1844042  1.367103e-05
## 26    B 0.95     1.528988e+01              1.1844042  1.654546e-05
## 27    B 0.95     1.528988e+01              1.1844042  9.530258e-06
## 28    B 1.00     3.333939e+00              0.5229577  1.367103e-05
## 29    B 1.00     3.333939e+00              0.5229577  1.654546e-05
## 30    B 1.00     3.333939e+00              0.5229577  9.530258e-06
##    Interpolated_CSCindex Replicate
## 1                     NA         1
## 2              0.8759742         2
## 3                     NA         3
## 4              1.2903964         1
## 5              1.2446656         2
## 6              1.1793651         3
## 7              1.4444412         1
## 8              1.3961964         2
## 9              1.4655281         3
## 10             1.6976308         1
## 11             1.7333023         2
## 12             1.3762001         3
## 13             1.3014638         1
## 14             1.2615771         2
## 15             1.1870717         3
## 16             1.1021841         1
## 17             1.0203974         2
## 18             0.9877920         3
## 19             1.0734851         1
## 20             0.9856642         2
## 21             0.9590929         3
## 22             1.0688436         1
## 23             0.9800468         2
## 24             0.9544515         3
## 25             1.0680116         1
## 26             0.9790399         2
## 27             0.9536195         3
## 28             1.0678482         1
## 29             0.9788421         2
## 30             0.9534560         3

Observe the CSCindex_Drug data.

# The list which shows information of all drugs.
head(CSCindex_list)
## [[1]]
##    Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1     A 0.55     35487.746764              4.5500784 -4.073213e-06
## 2     A 0.55     35487.746764              4.5500784 -3.395635e-07
## 3     A 0.55     35487.746764              4.5500784 -2.513739e-06
## 4     A 0.60      9029.249693              3.9556517  7.585941e-05
## 5     A 0.60      9029.249693              3.9556517  4.330917e-05
## 6     A 0.60      9029.249693              3.9556517  5.396774e-05
## 7     A 0.65      2563.495571              3.4088326  7.585941e-05
## 8     A 0.65      2563.495571              3.4088326  4.330917e-05
## 9     A 0.65      2563.495571              3.4088326  5.396774e-05
## 10    A 0.70       799.017714              2.9025564 -2.410455e-06
## 11    A 0.70       799.017714              2.9025564 -5.578633e-05
## 12    A 0.70       799.017714              2.9025564 -8.373344e-05
## 13    A 0.75       269.912538              2.4312231 -2.410455e-06
## 14    A 0.75       269.912538              2.4312231 -5.578633e-05
## 15    A 0.75       269.912538              2.4312231 -8.373344e-05
## 16    A 0.80        97.795429              1.9903186 -2.410455e-06
## 17    A 0.80        97.795429              1.9903186 -5.578633e-05
## 18    A 0.80        97.795429              1.9903186 -8.373344e-05
## 19    A 0.85        37.683516              1.5761514 -2.410455e-06
## 20    A 0.85        37.683516              1.5761514 -5.578633e-05
## 21    A 0.85        37.683516              1.5761514 -8.373344e-05
## 22    A 0.90        15.334361              1.1856657 -2.410455e-06
## 23    A 0.90        15.334361              1.1856657 -5.578633e-05
## 24    A 0.90        15.334361              1.1856657 -8.373344e-05
## 25    A 0.95         6.551195              0.8163205 -2.410455e-06
## 26    A 0.95         6.551195              0.8163205 -5.578633e-05
## 27    A 0.95         6.551195              0.8163205 -8.373344e-05
## 28    A 1.00         2.923326              0.4658773 -2.410455e-06
## 29    A 1.00         2.923326              0.4658773 -5.578633e-05
## 30    A 1.00         2.923326              0.4658773 -8.373344e-05
##    Interpolated_CSCindex Replicate
## 1              1.5242046         1
## 2              1.3865062         2
## 3              1.2892970         3
## 4              1.5543811         1
## 5              1.3531186         2
## 6              1.5164986         3
## 7              1.0638928         1
## 8              1.0730921         2
## 9              1.0260103         3
## 10             0.9457714         1
## 11             1.0165905         2
## 12             0.9892119         3
## 13             0.9470468         1
## 14             1.0461073         2
## 15             0.9904873         3
## 16             0.9474617         1
## 17             1.0557091         2
## 18             0.9909021         3
## 19             0.9476066         1
## 20             1.0590625         2
## 21             0.9910470         3
## 22             0.9476604         1
## 23             1.0603093         2
## 24             0.9911009         3
## 25             0.9476816         1
## 26             1.0607993         2
## 27             0.9911221         3
## 28             0.9476903         1
## 29             1.0610016         2
## 30             0.9911308         3
## 
## [[2]]
##    Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1     B 0.55     1.707704e+08              8.2324125            NA
## 2     B 0.55     1.707704e+08              8.2324125  0.000000e+00
## 3     B 0.55     1.707704e+08              8.2324125  0.000000e+00
## 4     B 0.60     1.289309e+07              7.1103569 -9.722378e-09
## 5     B 0.60     1.289309e+07              7.1103569 -9.935922e-09
## 6     B 0.60     1.289309e+07              7.1103569 -1.089025e-08
## 7     B 0.65     1.197164e+06              6.0781535 -2.032832e-08
## 8     B 0.65     1.197164e+06              6.0781535 -1.922399e-08
## 9     B 0.65     1.197164e+06              6.0781535 -4.968792e-08
## 10    B 0.70     1.325832e+05              5.1224883 -6.505348e-07
## 11    B 0.70     1.325832e+05              5.1224883 -8.810255e-07
## 12    B 0.70     1.325832e+05              5.1224883  1.106154e-07
## 13    B 0.75     1.709171e+04              4.2327854  1.367103e-05
## 14    B 0.75     1.709171e+04              4.2327854  1.654546e-05
## 15    B 0.75     1.709171e+04              4.2327854  9.530258e-06
## 16    B 0.80     2.514918e+03              3.4005238  1.367103e-05
## 17    B 0.80     2.514918e+03              3.4005238  1.654546e-05
## 18    B 0.80     2.514918e+03              3.4005238  9.530258e-06
## 19    B 0.85     4.156562e+02              2.6187342  1.367103e-05
## 20    B 0.85     4.156562e+02              2.6187342  1.654546e-05
## 21    B 0.85     4.156562e+02              2.6187342  9.530258e-06
## 22    B 0.90     7.614694e+01              1.8816524  1.367103e-05
## 23    B 0.90     7.614694e+01              1.8816524  1.654546e-05
## 24    B 0.90     7.614694e+01              1.8816524  9.530258e-06
## 25    B 0.95     1.528988e+01              1.1844042  1.367103e-05
## 26    B 0.95     1.528988e+01              1.1844042  1.654546e-05
## 27    B 0.95     1.528988e+01              1.1844042  9.530258e-06
## 28    B 1.00     3.333939e+00              0.5229577  1.367103e-05
## 29    B 1.00     3.333939e+00              0.5229577  1.654546e-05
## 30    B 1.00     3.333939e+00              0.5229577  9.530258e-06
##    Interpolated_CSCindex Replicate
## 1                     NA         1
## 2              0.8759742         2
## 3                     NA         3
## 4              1.2903964         1
## 5              1.2446656         2
## 6              1.1793651         3
## 7              1.4444412         1
## 8              1.3961964         2
## 9              1.4655281         3
## 10             1.6976308         1
## 11             1.7333023         2
## 12             1.3762001         3
## 13             1.3014638         1
## 14             1.2615771         2
## 15             1.1870717         3
## 16             1.1021841         1
## 17             1.0203974         2
## 18             0.9877920         3
## 19             1.0734851         1
## 20             0.9856642         2
## 21             0.9590929         3
## 22             1.0688436         1
## 23             0.9800468         2
## 24             0.9544515         3
## 25             1.0680116         1
## 26             0.9790399         2
## 27             0.9536195         3
## 28             1.0678482         1
## 29             0.9788421         2
## 30             0.9534560         3
# Drug A
head(CSCindex_DrugA)
##   Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1    A 0.55         35487.75               4.550078 -4.073213e-06
## 2    A 0.55         35487.75               4.550078 -3.395635e-07
## 3    A 0.55         35487.75               4.550078 -2.513739e-06
## 4    A 0.60          9029.25               3.955652  7.585941e-05
## 5    A 0.60          9029.25               3.955652  4.330917e-05
## 6    A 0.60          9029.25               3.955652  5.396774e-05
##   Interpolated_CSCindex Replicate
## 1              1.524205         1
## 2              1.386506         2
## 3              1.289297         3
## 4              1.554381         1
## 5              1.353119         2
## 6              1.516499         3
# Drug B
head(CSCindex_DrugB)
##   Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1    B 0.55        170770357               8.232412            NA
## 2    B 0.55        170770357               8.232412  0.000000e+00
## 3    B 0.55        170770357               8.232412  0.000000e+00
## 4    B 0.60         12893086               7.110357 -9.722378e-09
## 5    B 0.60         12893086               7.110357 -9.935922e-09
## 6    B 0.60         12893086               7.110357 -1.089025e-08
##   Interpolated_CSCindex Replicate
## 1                    NA         1
## 2             0.8759742         2
## 3                    NA         3
## 4             1.2903964         1
## 5             1.2446656         2
## 6             1.1793651         3

Part 3.4: Reconsider SVI range, according to NA value possibly present.

According to the calculated CSC index derived from interpolation, values from some replicates may fall outside the interpolatable range. This could potentially lead to the occurrence of NA values. If NA values are present due to interpolation issues, they are likely to occur at the highest or lowest SVI. Therefore, SVIs with NA values can be excluded and replaced with a new SVI range using our pipeline below. However, NA values may also arise from other reasons, so it’s important to thoroughly check the data.

3.4.1 Check whether NA is present in the data.

# Create a blank vector to store SVI that contains removable NA.
SVI_wtNAremovable_vector <- vector()

# Check whether NA value is present in any SVI.
for (CSCindex_DrugX in CSCindex_list){
  
  print(paste("Start SVI range re-considering analysis of drug", CSCindex_DrugX$Drug[1]))
  
    if (anyNA(CSCindex_DrugX)) 
      {
        print(paste0("CSCindex_Drug", CSCindex_DrugX$Drug[1], " contains NA."))
      
        # Show the rows that contain NA value.
        DrugX_Rows_with_NA <- CSCindex_DrugX[!complete.cases(CSCindex_DrugX), ]
        print(DrugX_Rows_with_NA)
        
          # Show SVIs that contain NA value.
            SVI_wtNA <- unique(DrugX_Rows_with_NA$SVI)
            print(paste0("SVI = ", SVI_wtNA, " contains NA."))
            
            # Check whether the occurrence of NA values is removable or if all results should be rechecked. 
            if (SVI_wtNA == min(SVI_Range) | SVI_wtNA == max(SVI_Range)){
                # Change variable name to`SVI_wtNAremovable` for further analysis.
                  SVI_wtNAremovable <- SVI_wtNA
                  
                # If NA values occur in the highest or lowest SVI, this might be due to interpolate issue. Thus, the lowest/highest SVI can be excluded.
                  print(paste0("SVI = ", SVI_wtNAremovable, " contains NA at highest or lowest SVI, thus this SVI is removable."))
                  
                # Store removable SVIs into a created vector (`SVI_wtNAremovable_vector`).
                  SVI_wtNAremovable_vector <- c(SVI_wtNAremovable_vector, 
                                                  SVI_wtNAremovable
                                                )
              } 
            else 
              {
              # If NA values occur in other SVIs, the data should be rechecked.
                print(paste0("SVI = ", SVI_wtNA, " contains NA, all data should be re-checked."))
              }
          
      } 
    else 
      {
          print(paste0("CSCindex_Drug", CSCindex_DrugX$Drug[1], " does not contain NA"))
      }
  
  print(paste("Finish SVI range re-considering analysis of drug", CSCindex_DrugX$Drug[1]))
  print("===========================================")

  }
## [1] "Start SVI range re-considering analysis of drug A"
## [1] "CSCindex_DrugA does not contain NA"
## [1] "Finish SVI range re-considering analysis of drug A"
## [1] "==========================================="
## [1] "Start SVI range re-considering analysis of drug B"
## [1] "CSCindex_DrugB contains NA."
##   Drug  SVI Concentration_pM log10_Concentration_pM m_Slope
## 1    B 0.55        170770357               8.232412      NA
## 3    B 0.55        170770357               8.232412       0
##   Interpolated_CSCindex Replicate
## 1                    NA         1
## 3                    NA         3
## [1] "SVI = 0.55 contains NA."
## [1] "SVI = 0.55 contains NA at highest or lowest SVI, thus this SVI is removable."
## [1] "Finish SVI range re-considering analysis of drug B"
## [1] "==========================================="

Observe the SVIs that contain NA values.

unique(SVI_wtNAremovable_vector)
## [1] 0.55

3.4.2 Exclude SVI that contain NA values and define the selected SVI range.

# Define new SVI range and SVI values (without SVI that contain NA values).
  noNA_SVI_Range <- Desired_SVIvalues[!Desired_SVIvalues %in% SVI_wtNAremovable]
  print(paste0("New SVI values(no NA) are ", paste(noNA_SVI_Range, collapse = ", ")))
## [1] "New SVI values(no NA) are 1, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6"
# Create a blank list to store `CSCindex_noNA` information.
  CSCindex_noNA_list <- list()

# Exclude the removable SVI ('SVI_wtNAremovable') from `CSCindex` data frame.
for (CSCindex_DrugX in CSCindex_list){
    # Exclude SVI that contains NA values
      CSCindex_noNA_DrugX <- dplyr::filter(CSCindex_DrugX, 
                                            SVI != SVI_wtNAremovable
                                           )
      CSCindex_noNA_DrugX
    
    # Rename the data frame to show the drug name.
      ## Extract the drug name.
      Drug_Name <- CSCindex_noNA_DrugX$Drug[1]
      
      ## Rename the data frame.
      CSCindex_noNA_DrugX_Data <- assign(paste0("CSCindex_noNA_Drug", Drug_Name),
                                          CSCindex_noNA_DrugX
                                         ) 
      
    # Store the data frame into the list `CSCindex_noNA_list`.
      CSCindex_noNA_list[[length(CSCindex_noNA_list)+1]] <- CSCindex_noNA_DrugX_Data
    
  }

Observe the CSCindex_noNA_Drug data.

# The list which shows information of all drugs.
head(CSCindex_noNA_list)
## [[1]]
##    Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1     A 0.60      9029.249693              3.9556517  7.585941e-05
## 2     A 0.60      9029.249693              3.9556517  4.330917e-05
## 3     A 0.60      9029.249693              3.9556517  5.396774e-05
## 4     A 0.65      2563.495571              3.4088326  7.585941e-05
## 5     A 0.65      2563.495571              3.4088326  4.330917e-05
## 6     A 0.65      2563.495571              3.4088326  5.396774e-05
## 7     A 0.70       799.017714              2.9025564 -2.410455e-06
## 8     A 0.70       799.017714              2.9025564 -5.578633e-05
## 9     A 0.70       799.017714              2.9025564 -8.373344e-05
## 10    A 0.75       269.912538              2.4312231 -2.410455e-06
## 11    A 0.75       269.912538              2.4312231 -5.578633e-05
## 12    A 0.75       269.912538              2.4312231 -8.373344e-05
## 13    A 0.80        97.795429              1.9903186 -2.410455e-06
## 14    A 0.80        97.795429              1.9903186 -5.578633e-05
## 15    A 0.80        97.795429              1.9903186 -8.373344e-05
## 16    A 0.85        37.683516              1.5761514 -2.410455e-06
## 17    A 0.85        37.683516              1.5761514 -5.578633e-05
## 18    A 0.85        37.683516              1.5761514 -8.373344e-05
## 19    A 0.90        15.334361              1.1856657 -2.410455e-06
## 20    A 0.90        15.334361              1.1856657 -5.578633e-05
## 21    A 0.90        15.334361              1.1856657 -8.373344e-05
## 22    A 0.95         6.551195              0.8163205 -2.410455e-06
## 23    A 0.95         6.551195              0.8163205 -5.578633e-05
## 24    A 0.95         6.551195              0.8163205 -8.373344e-05
## 25    A 1.00         2.923326              0.4658773 -2.410455e-06
## 26    A 1.00         2.923326              0.4658773 -5.578633e-05
## 27    A 1.00         2.923326              0.4658773 -8.373344e-05
##    Interpolated_CSCindex Replicate
## 1              1.5543811         1
## 2              1.3531186         2
## 3              1.5164986         3
## 4              1.0638928         1
## 5              1.0730921         2
## 6              1.0260103         3
## 7              0.9457714         1
## 8              1.0165905         2
## 9              0.9892119         3
## 10             0.9470468         1
## 11             1.0461073         2
## 12             0.9904873         3
## 13             0.9474617         1
## 14             1.0557091         2
## 15             0.9909021         3
## 16             0.9476066         1
## 17             1.0590625         2
## 18             0.9910470         3
## 19             0.9476604         1
## 20             1.0603093         2
## 21             0.9911009         3
## 22             0.9476816         1
## 23             1.0607993         2
## 24             0.9911221         3
## 25             0.9476903         1
## 26             1.0610016         2
## 27             0.9911308         3
## 
## [[2]]
##    Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1     B 0.60     1.289309e+07              7.1103569 -9.722378e-09
## 2     B 0.60     1.289309e+07              7.1103569 -9.935922e-09
## 3     B 0.60     1.289309e+07              7.1103569 -1.089025e-08
## 4     B 0.65     1.197164e+06              6.0781535 -2.032832e-08
## 5     B 0.65     1.197164e+06              6.0781535 -1.922399e-08
## 6     B 0.65     1.197164e+06              6.0781535 -4.968792e-08
## 7     B 0.70     1.325832e+05              5.1224883 -6.505348e-07
## 8     B 0.70     1.325832e+05              5.1224883 -8.810255e-07
## 9     B 0.70     1.325832e+05              5.1224883  1.106154e-07
## 10    B 0.75     1.709171e+04              4.2327854  1.367103e-05
## 11    B 0.75     1.709171e+04              4.2327854  1.654546e-05
## 12    B 0.75     1.709171e+04              4.2327854  9.530258e-06
## 13    B 0.80     2.514918e+03              3.4005238  1.367103e-05
## 14    B 0.80     2.514918e+03              3.4005238  1.654546e-05
## 15    B 0.80     2.514918e+03              3.4005238  9.530258e-06
## 16    B 0.85     4.156562e+02              2.6187342  1.367103e-05
## 17    B 0.85     4.156562e+02              2.6187342  1.654546e-05
## 18    B 0.85     4.156562e+02              2.6187342  9.530258e-06
## 19    B 0.90     7.614694e+01              1.8816524  1.367103e-05
## 20    B 0.90     7.614694e+01              1.8816524  1.654546e-05
## 21    B 0.90     7.614694e+01              1.8816524  9.530258e-06
## 22    B 0.95     1.528988e+01              1.1844042  1.367103e-05
## 23    B 0.95     1.528988e+01              1.1844042  1.654546e-05
## 24    B 0.95     1.528988e+01              1.1844042  9.530258e-06
## 25    B 1.00     3.333939e+00              0.5229577  1.367103e-05
## 26    B 1.00     3.333939e+00              0.5229577  1.654546e-05
## 27    B 1.00     3.333939e+00              0.5229577  9.530258e-06
##    Interpolated_CSCindex Replicate
## 1              1.2903964         1
## 2              1.2446656         2
## 3              1.1793651         3
## 4              1.4444412         1
## 5              1.3961964         2
## 6              1.4655281         3
## 7              1.6976308         1
## 8              1.7333023         2
## 9              1.3762001         3
## 10             1.3014638         1
## 11             1.2615771         2
## 12             1.1870717         3
## 13             1.1021841         1
## 14             1.0203974         2
## 15             0.9877920         3
## 16             1.0734851         1
## 17             0.9856642         2
## 18             0.9590929         3
## 19             1.0688436         1
## 20             0.9800468         2
## 21             0.9544515         3
## 22             1.0680116         1
## 23             0.9790399         2
## 24             0.9536195         3
## 25             1.0678482         1
## 26             0.9788421         2
## 27             0.9534560         3
# Drug A
head(CSCindex_noNA_DrugA)
##   Drug  SVI Concentration_pM log10_Concentration_pM      m_Slope
## 1    A 0.60         9029.250               3.955652 7.585941e-05
## 2    A 0.60         9029.250               3.955652 4.330917e-05
## 3    A 0.60         9029.250               3.955652 5.396774e-05
## 4    A 0.65         2563.496               3.408833 7.585941e-05
## 5    A 0.65         2563.496               3.408833 4.330917e-05
## 6    A 0.65         2563.496               3.408833 5.396774e-05
##   Interpolated_CSCindex Replicate
## 1              1.554381         1
## 2              1.353119         2
## 3              1.516499         3
## 4              1.063893         1
## 5              1.073092         2
## 6              1.026010         3
# Drug B
head(CSCindex_noNA_DrugB)
##   Drug  SVI Concentration_pM log10_Concentration_pM       m_Slope
## 1    B 0.60         12893086               7.110357 -9.722378e-09
## 2    B 0.60         12893086               7.110357 -9.935922e-09
## 3    B 0.60         12893086               7.110357 -1.089025e-08
## 4    B 0.65          1197164               6.078153 -2.032832e-08
## 5    B 0.65          1197164               6.078153 -1.922399e-08
## 6    B 0.65          1197164               6.078153 -4.968792e-08
##   Interpolated_CSCindex Replicate
## 1              1.290396         1
## 2              1.244666         2
## 3              1.179365         3
## 4              1.444441         1
## 5              1.396196         2
## 6              1.465528         3

Part 3.5: Find AUC of CSC index according to the selected SVI range.

3.5.1 Calculate AUC of CSC index for vehicle control.

  # Define information.
    VehicleControl_df <- data.frame(Drug = "Control", 
                                      SVI = CSCindex_noNA_list[[1]]$SVI,
                                      Interpolated_CSCindex = 1,
                                      Replicate = CSCindex_noNA_list[[1]]$Replicate
                                    )

  # Calculate AUC of CSC index for each replicate.
    AUC_Control <- VehicleControl_df %>%
                    group_by(Replicate) %>%
                    summarise(AUC_Control = trapz(SVI, Interpolated_CSCindex)) %>% 
                    cbind(Drug = VehicleControl_df$Drug[1])
    
  # VObserve the `AUC_Control` data.
    AUC_Control
##   Replicate AUC_Control    Drug
## 1         1         0.4 Control
## 2         2         0.4 Control
## 3         3         0.4 Control

3.5.2 Calculate normalized CSC index’s AUC of each drug.

# Create a blank list to store `NormalizedAUC` information.
  NormalizedAUC_list <- list()

# Calculate AUC of CSC index.
for (CSCindex_noNA_DrugX in CSCindex_noNA_list){
    # Step 1: Calculate AUC of CSC index for each Replicate.
      AUC_DrugX <- CSCindex_noNA_DrugX %>%
                    group_by(Replicate) %>%
                    summarise(AUC = trapz(SVI, Interpolated_CSCindex)) %>% 
                    cbind(Drug = CSCindex_noNA_DrugX$Drug[1])
    
    # Step 2: Calculate normalized CSC index's AUC by divided by AUC of the vehicle control.
      ## Add AUC of the vehicle control the data frame.
        AUC_DrugX <- cbind(AUC_DrugX, AUC_Control = AUC_Control$AUC_Control)
        NormalizedAUC_DrugX <- dplyr::mutate(AUC_DrugX, 
                                              Normalized_AUC = AUC/AUC_Control
                                             )
      
      ## Reorder columns.
        NormalizedAUC_DrugX <- select(NormalizedAUC_DrugX, 
                                        Drug, 
                                        Replicate, 
                                        everything()
                                      )
      
    # Rename the data frame to show the drug name.
      ## Extract the drug name.
        Drug_Name <- NormalizedAUC_DrugX$Drug[1]
          
      ## Rename the data frame.
        NormalizedAUC_DrugX_Data <- assign(paste0("NormalizedAUC_Drug", Drug_Name), 
                                            NormalizedAUC_DrugX
                                           ) 
        
    # Store the data frame into the list `NormalizedAUC_list`.
        NormalizedAUC_list[[length(NormalizedAUC_list)+1]] <- NormalizedAUC_DrugX_Data
    
  }

Observe the NormalizedAUC_Drug data.

# The list which shows information of all drugs.
head(NormalizedAUC_list)
## [[1]]
##   Drug Replicate       AUC AUC_Control Normalized_AUC
## 1    A         1 0.3999078         0.4      0.9997696
## 2    A         2 0.4289365         0.4      1.0723413
## 3    A         3 0.4111848         0.4      1.0279620
## 
## [[2]]
##   Drug Replicate       AUC AUC_Control Normalized_AUC
## 1    B         1 0.4967591         0.4       1.241898
## 2    B         2 0.4733989         0.4       1.183497
## 3    B         3 0.4475083         0.4       1.118771
# Drug A
head(NormalizedAUC_DrugA)
##   Drug Replicate       AUC AUC_Control Normalized_AUC
## 1    A         1 0.3999078         0.4      0.9997696
## 2    A         2 0.4289365         0.4      1.0723413
## 3    A         3 0.4111848         0.4      1.0279620
# Drug B
head(NormalizedAUC_DrugB)
##   Drug Replicate       AUC AUC_Control Normalized_AUC
## 1    B         1 0.4967591         0.4       1.241898
## 2    B         2 0.4733989         0.4       1.183497
## 3    B         3 0.4475083         0.4       1.118771

Part 3.6: Create summary analysis.

# Combine all drug into a data frame.
  NormalizedAUC_AllDrugs <- bind_rows(NormalizedAUC_list)
  write.csv(NormalizedAUC_AllDrugs, 
              paste0("RawResult", "_NormalizedCSC.AUC_AllDrugs.csv"), row.names = FALSE)
  
# Summarize the analysis.
  Summary_NormalizedAUC_AllDrugs <- NormalizedAUC_AllDrugs %>%
                                      group_by(Drug) %>%
                                      summarise_at(vars(Normalized_AUC), 
                                                   list(Mean_Normalized_AUC = mean, 
                                                        SD_Normalized_AUC   = sd)
                                                   )
  # Write the `Summary_NormalizedAUC_AllDrugs`  into a `.csv` file. 
    write.csv(Summary_NormalizedAUC_AllDrugs, "Summary_NormalizedCSC.AUC_AllDrugs.csv", row.names = FALSE)

Observe the Summary_NormalizedCSCindexAUC_AllDrugs data.

head(Summary_NormalizedAUC_AllDrugs)
## # A tibble: 2 × 3
##   Drug  Mean_Normalized_AUC SD_Normalized_AUC
##   <chr>               <dbl>             <dbl>
## 1 A                    1.03            0.0366
## 2 B                    1.18            0.0616

Section 4: Statistical test

4.1 Normality test

To determine whether the data follows a normal distribution, the normality test should be performed.

  shapiro.test(NormalizedAUC_AllDrugs$Normalized_AUC)
## 
##  Shapiro-Wilk normality test
## 
## data:  NormalizedAUC_AllDrugs$Normalized_AUC
## W = 0.95952, p-value = 0.8161

For the example dataset, the result showed that the data is normally distributed.

4.2 Statistical test

According to the normal distribution of the data, a t-test was used for statistical testing.  

If your data does not follow a normal distribution, a non-parametric test like the “Wilcoxon rank-sum test” should be used instead.
Here, we also provide the choice of statistical tests as shown below.

# Wilcoxon rank-sum test
  Stat_NormalizedAUC_Wilcox <- compare_means(Normalized_AUC ~ Drug, 
                                        data = NormalizedAUC_AllDrugs,
                                        method = "wilcox.test"
                                      )

# T-test
  Stat_NormalizedAUC_Ttest <- compare_means(Normalized_AUC ~ Drug, 
                                        data = NormalizedAUC_AllDrugs, 
                                        method = "t.test"
                                      )

  # Write the `Stat_NormalizedAUC_Ttest`  into a `.csv` file. 
    write.csv(Stat_NormalizedAUC_Ttest, 
                paste0("Stat", "_NormalizedCSC.AUC.csv"), row.names = FALSE)

Observe the Stat_NormalizedAUC_Ttest data.

head(Stat_NormalizedAUC_Ttest)
## # A tibble: 1 × 8
##   .y.            group1 group2      p p.adj p.format p.signif method
##   <chr>          <chr>  <chr>   <dbl> <dbl> <chr>    <chr>    <chr> 
## 1 Normalized_AUC A      B      0.0327 0.033 0.033    *        T-test

Section 5: Data visualization

Data visualization is presented as a bar graph in an object named NormalizedAUC_plot and saved as a .png file.

NormalizedAUC_plot <- ggplot(Summary_NormalizedAUC_AllDrugs, aes(x = Drug)) +
                        geom_bar(aes(y = Mean_Normalized_AUC, fill = Drug), 
                                 stat = "identity", alpha = 0.8) +
  
                        geom_errorbar(aes(ymin = Mean_Normalized_AUC - SD_Normalized_AUC, 
                                          ymax = Mean_Normalized_AUC + SD_Normalized_AUC),
                                          width = 0.1, position = position_dodge(0.9)) +
  
                        scale_fill_viridis(discrete = TRUE, option = "H")  +
  
                        scale_y_continuous(breaks = seq(0, (max(Summary_NormalizedAUC_AllDrugs$Mean_Normalized_AUC)+0.25), 
                                                        by = 0.25)) +
  
                        labs(title = "Comparing CSC content among the drugs",
                                 x = "Drugs",
                                 y = "Normalized CSC index's AUC") +
  
                        theme_classic() +
                        theme(plot.title = element_text(hjust = 0.5)) +
                        theme(legend.position = "none") 

# Manually annotate the statistical significance
  NormalizedAUC_plot_wtStat <- NormalizedAUC_plot + 
                                  annotate("text", 
                                            x = 1.5, 
                                            y = 0.1 + max(Summary_NormalizedAUC_AllDrugs$Mean_Normalized_AUC), 
                                            label = "*", 
                                            size = 8)
  
# Save the plot as a `.png` file.
  ggsave('NormalizedAUC_plot.png', 
         width = 4, height = 4, 
         dpi = 300, units = 'in')
  print(paste0("The .png file was saved as '", "NormalizedAUC_plot.png'"))
## [1] "The .png file was saved as 'NormalizedAUC_plot.png'"


Figure 3: Comparing CSC content among cytotoxic drugs across a range of 3D multi-spheroid’s dose-response.