@@ -36,12 +36,11 @@ compute_auc <- function(roc_df) {
3636 sum((x [- 1 ] - x [- length(x )]) * (y [- 1 ] + y [- length(y )]) / 2 )
3737}
3838
39- roc_plot <- function (df , output_path = " roc_curve.png " ) {
39+ compute_roc_and_auc <- function (df ) {
4040 if (! all(c(" y_true" , " y_score" ) %in% colnames(df ))) {
4141 if (! (" y_pred" %in% colnames(df ))) {
4242 stop(" Expected columns y_true and y_score (or y_pred) in input CSV." , call. = FALSE )
4343 }
44- message(" Column y_score not found, using y_pred as score (may degrade ROC)." )
4544 df $ y_score <- df $ y_pred
4645 }
4746
@@ -51,31 +50,106 @@ roc_plot <- function(df, output_path = "roc_curve.png") {
5150 roc_df <- compute_roc(y_true , y_score )
5251 auc <- compute_auc(roc_df )
5352
54- p <- ggplot(roc_df , aes(x = fpr , y = tpr )) +
55- geom_line(color = " #67a9cf" , size = 1 ) +
53+ list (roc_df = roc_df , auc = auc )
54+ }
55+
56+ roc_plot_combined <- function (roc_data_list , output_path = " roc_curve.png" , title = " ROC Curves" ) {
57+ # Combine all ROC data with labels
58+ all_roc_data <- data.frame ()
59+
60+ for (i in seq_along(roc_data_list )) {
61+ roc_df <- roc_data_list [[i ]]$ roc_df
62+ auc <- roc_data_list [[i ]]$ auc
63+ label <- roc_data_list [[i ]]$ label
64+
65+ # Label format: "fold_num (AUC = X.XXX)"
66+ roc_df $ fold <- sprintf(" %s (AUC = %.3f)" , label , auc )
67+ all_roc_data <- rbind(all_roc_data , roc_df )
68+ }
69+
70+ # Generate color palette
71+ n_folds <- length(roc_data_list )
72+ colors <- rainbow(n_folds )
73+
74+ p <- ggplot(all_roc_data , aes(x = fpr , y = tpr , color = fold )) +
75+ geom_line(linewidth = 1 ) +
5676 geom_abline(slope = 1 , intercept = 0 , linetype = " dashed" , color = " grey60" ) +
5777 coord_equal(xlim = c(0 , 1 ), ylim = c(0 , 1 )) +
78+ scale_color_manual(values = colors , name = " K-Fold" ) +
5879 labs(
5980 x = " False Positive Rate" ,
6081 y = " True Positive Rate" ,
61- title = sprintf( " ROC curve (AUC = %.3f) " , auc )
82+ title = title
6283 ) +
63- theme_minimal()
64-
65- ggsave(output_path , plot = p , width = 6 , height = 6 , dpi = 300 )
84+ theme_minimal() +
85+ theme(
86+ legend.position = " right" ,
87+ legend.title = element_text(size = 10 ),
88+ legend.text = element_text(size = 9 )
89+ )
90+
91+ ggsave(output_path , plot = p , width = 8 , height = 6 , dpi = 300 )
92+ message(sprintf(" Generated combined ROC curve: %s" , output_path ))
6693}
6794
6895main <- function () {
6996 args <- commandArgs(trailingOnly = TRUE )
7097 if (length(args ) < 1 ) {
71- stop(" Usage: Rscript roc_curve.R <test_predictions.csv> [output_path]" , call. = FALSE )
98+ stop(" Usage: Rscript roc_curve.R <test_predictions1.csv> [test_predictions2.csv ...]" , call. = FALSE )
99+ }
100+
101+ csv_files <- args
102+
103+ # Extract feature_extractor and algorithm from first file
104+ # Expected format: {feature_extractor}.{algorithm}.{fold}.test_predictions.csv
105+ first_file <- basename(csv_files [1 ])
106+ parts <- strsplit(first_file , " \\ ." )[[1 ]]
107+
108+ if (length(parts ) > = 4 ) {
109+ feature_extractor <- parts [1 ]
110+ algorithm <- parts [2 ]
111+ output_path <- sprintf(" %s.%s.roc_auc_curve.png" , feature_extractor , algorithm )
112+ } else {
113+ output_path <- " roc_auc_curve.png"
72114 }
73115
74- test_predictions <- args [1 ]
75- output_path <- if (length(args ) > = 2 ) args [2 ] else " roc_auc_curve.png"
116+ # Process all CSV files and collect ROC data
117+ roc_data_list <- list ()
118+
119+ for (csv_file in csv_files ) {
120+ if (! file.exists(csv_file )) {
121+ warning(sprintf(" File not found: %s, skipping..." , csv_file ))
122+ next
123+ }
124+
125+ # Read and process
126+ df <- read_csv(csv_file , show_col_types = FALSE )
127+ base_name <- tools :: file_path_sans_ext(basename(csv_file ))
128+
129+ # Extract fold number from filename (e.g., model.algorithm.0.test_predictions -> 0)
130+ file_parts <- strsplit(base_name , " \\ ." )[[1 ]]
131+ if (length(file_parts ) > = 3 ) {
132+ fold_num <- file_parts [3 ]
133+ label <- fold_num
134+ } else {
135+ # Fallback: try to extract number from end of filename
136+ fold_match <- regmatches(base_name , regexpr(" \\ d+" , base_name ))
137+ label <- if (length(fold_match ) > 0 ) fold_match else base_name
138+ }
139+
140+ roc_data <- compute_roc_and_auc(df )
141+ roc_data $ label <- label
142+ roc_data_list [[length(roc_data_list ) + 1 ]] <- roc_data
143+
144+ message(sprintf(" Processed %s: AUC = %.3f" , csv_file , roc_data $ auc ))
145+ }
146+
147+ if (length(roc_data_list ) == 0 ) {
148+ stop(" No valid CSV files found to process." , call. = FALSE )
149+ }
76150
77- df <- read_csv( test_predictions , show_col_types = FALSE )
78- roc_plot( df , output_path )
151+ # Generate combined plot
152+ roc_plot_combined( roc_data_list , output_path )
79153}
80154
81155if (identical(environment(), globalenv())) {
0 commit comments