# === Load libraries === library(jsonlite) library(grid) library(gridExtra) # === 1. Baca file JSON === data <- fromJSON("summary.json", simplifyVector = FALSE) # === 2. Ambil metadata === fold_variance <- data$fold_variance robustness_score <- data$robustness_score total_train_time <- data$total_train_time_sec class_labels <- data$class_labels table_data <- data.frame(Label = class_labels) # === 3. Layout proporsional === grid.newpage() pushViewport(viewport(layout = grid.layout(2, 1, heights = unit(c(1, 2), "null")))) # === 3a. Header teks metadata === pushViewport(viewport(layout.pos.row = 1)) grid.text("Model Summary", x = 0.5, y = 0.8, gp = gpar(fontsize = 16, fontface = "bold")) grid.text(sprintf("Fold Variance: %.6f", fold_variance), x = 0.5, y = 0.55, gp = gpar(fontsize = 12, col = "#333333")) grid.text(sprintf("Robustness Score: %.6f", robustness_score), x = 0.5, y = 0.40, gp = gpar(fontsize = 12, col = "#333333")) grid.text(sprintf("Total Train Time: %.2f sec", total_train_time), x = 0.5, y = 0.25, gp = gpar(fontsize = 12, col = "#333333")) popViewport() # === 3b. Tabel class labels di bawah === pushViewport(viewport(layout.pos.row = 2)) # Judul class labels — posisikan sedikit lebih dekat ke tabel grid.text("Class Labels", x = 0.5, y = 0.78, gp = gpar(fontsize = 14, fontface = "bold", col = "#222222")) # Tema tabel elegan dan kompak table_theme <- gridExtra::ttheme_default( core = list( fg_params = list(cex = 0.85, col = "#222222"), bg_params = list(fill = rep("#f9f9f9", nrow(table_data)), col = NA) ), colhead = list( fg_params = list(cex = 0.9, fontface = "bold", col = "#222222"), bg_params = list(fill = "#e8e8e8", col = NA) ), padding = unit(c(2, 4), "mm") ) # Buat tabel dan posisikan tepat di bawah judul table_grob <- gridExtra::tableGrob( table_data, rows = NULL, theme = table_theme ) # Posisi tabel lebih dekat ke judul dan tetap proporsional grid.draw(editGrob(table_grob, vp = viewport(x = 0.5, y = 0.43, width = 0.25, height = 0.4))) popViewport()