Skip to content

Commit b96d438

Browse files
committed
Enhance feature rescoring by adding distinct feature subtype aggregation and introducing wide table functions for global score calculations
1 parent b356109 commit b96d438

1 file changed

Lines changed: 118 additions & 4 deletions

File tree

‎R/feature_rescoring.R‎

Lines changed: 118 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,19 +485,23 @@ top_features <- feature_summary |>
485485
dplyr::filter(
486486
sign == "NEG",
487487
rank_sd <= threshold_sd_rank
488-
) |>
488+
) |>
489+
dplyr::group_by(species, drug_label, drug_or_class, feature_type, Variable) |>
490+
dplyr::mutate( n_subtype = dplyr::n_distinct(feature_subtype),
491+
subtype_csv = paste(sort(unique(feature_subtype)), collapse = ",") ) |>
492+
dplyr::ungroup() |>
489493
dplyr::group_by(drug_label, drug_or_class) |>
490494
dplyr::filter(
491495
n_seeds == max(n_seeds),
492496
mean_rank_score >= quantile(mean_rank_score, rank_score_quantile)
493497
) |>
494498
dplyr::ungroup() |>
495-
dplyr::select(
499+
dplyr::distinct(
496500
species, drug_label, drug_or_class,
497-
feature_type, feature_subtype, Variable,
501+
feature_type, feature_subtype, Variable, n_subtype, subtype_csv,
498502
mean_rank_score, mean_rank, best_rank,
499503
median_rank, mean_contribution, median_contribution,
500-
n_seeds, rank_sd,
504+
n_seeds, rank_sd,
501505
sign_consistent, sign
502506
) |>
503507
dplyr::filter(sign_consistent)
@@ -614,3 +618,113 @@ dplyr::rename(drug_or_class = drug_or_class_csv) |>
614618

615619
return(unique_clusters)
616620
}
621+
622+
#' build the wide table for features while calculating the global score and breadth
623+
#'
624+
#' First aggregate the feature subtype to feature type level, then calculate the global score and breadth for each feature type across all drugs/classes.
625+
#' Then create a wide table representation
626+
#'
627+
#' @param feature_summary The tibble of summarized features across seeds generated from `summariseFeatureAcrossSeeds()`
628+
#'
629+
#' @returns a wide tibble with each drug/class score and global score for individual features from different scales.
630+
#'
631+
#' @export
632+
#' @examples
633+
buildFeatureWideTable <- function(feature_summary
634+
) {
635+
636+
id_cols = c("drug_label", "drug_or_class")
637+
638+
adv_feat_summary <- feature_summary |>
639+
dplyr::group_by(
640+
species, drug_label, drug_or_class, feature_type, Variable
641+
) |>
642+
dplyr::summarise(
643+
n_subtype = dplyr::n_distinct(feature_subtype),
644+
subtype_csv = paste(sort(unique(feature_subtype)), collapse = ","),
645+
type_mean_score = mean(mean_rank_score, na.rm = TRUE),
646+
type_median_rank = median(median_rank, na.rm = TRUE),
647+
type_rank_sd = sd(median_rank, na.rm = TRUE),
648+
frequency = sum(n_seeds),
649+
sign = if (dplyr::n_distinct(sign) == 1) dplyr::first(sign) else "MIXED",
650+
.groups = "drop"
651+
) |>
652+
tidyr::unite(
653+
col = "model_id",
654+
dplyr::all_of(id_cols),
655+
sep = ".",
656+
remove = FALSE
657+
)
658+
659+
row_cols = c("species", "feature_type", "Variable")
660+
661+
global_summary <- adv_feat_summary |>
662+
dplyr::group_by(dplyr::across(dplyr::all_of(row_cols))) |>
663+
dplyr::summarise(
664+
global_breadth = dplyr::n_distinct(model_id),
665+
global_score = mean(type_mean_score, na.rm = TRUE),
666+
global_sd = sd(type_rank_sd, na.rm = TRUE),
667+
.groups = "drop"
668+
)
669+
670+
wide_cols = c("sign", "frequency", "type_mean_score")
671+
672+
wide_part <- adv_feat_summary |>
673+
dplyr::select(
674+
dplyr::all_of(row_cols),
675+
model_id,
676+
dplyr::all_of(wide_cols)
677+
) |>
678+
tidyr::pivot_wider(
679+
names_from = model_id,
680+
values_from = dplyr::all_of(wide_cols),
681+
names_sep = "."
682+
)
683+
684+
wide_table <- dplyr::left_join(wide_part, global_summary, by = row_cols) |>
685+
dplyr::arrange(dplyr::desc(global_breadth), dplyr::desc(global_score))
686+
687+
return(wide_table)
688+
}
689+
690+
691+
#------------------------------------------------------------
692+
# Cluster-wide table:
693+
# one row per cluster, with per-model columns
694+
# and global_cluster_score / global_cluster_breadth
695+
#------------------------------------------------------------
696+
buildClusterWideTable <- function(cluster_summary,
697+
id_cols = c("species", "drug_label", "drug_or_class"),
698+
row_cols = c("species", "cluster"),
699+
score_col = "cluster_mean_rank_score") {
700+
required_cols <- c(
701+
id_cols, row_cols,
702+
score_col, "cluster_rank_score_sd",
703+
"cluster_best_rank", "frequency",
704+
"n_variables", "n_feature_types"
705+
)
706+
stopifnot(all(required_cols %in% names(cluster_summary)))
707+
708+
build <- buildFeatureWideTable(
709+
.data = cluster_summary,
710+
id_cols = id_cols,
711+
row_cols = row_cols,
712+
score_col = score_col,
713+
breadth_name = "global_breadth",
714+
wide_cols = c(
715+
"cluster_mean_rank_score",
716+
"cluster_rank_score_sd",
717+
"cluster_best_rank",
718+
"frequency",
719+
"n_variables",
720+
"n_feature_types"
721+
)
722+
)
723+
724+
build |>
725+
dplyr::rename(
726+
global_cluster_score = global_score,
727+
global_cluster_sd = global_sd
728+
) |>
729+
dplyr::arrange(dplyr::desc(global_cluster_score), dplyr::desc(global_breadth))
730+
}

0 commit comments

Comments
 (0)