Nothing
.determine_preprocessing_parameters <- function(
cl = NULL,
data,
feature_info_list,
settings,
message_indent = 0L,
verbose = FALSE
) {
if (!is(data, "dataObject")) {
..error_reached_unreachable_code(
".determine_preprocessing_parameters: data is not a dataObject."
)
}
if (is_empty(data)) ..error_data_set_is_empty()
if (!has_feature_data(data)) ..error_data_set_has_no_features()
# Remove samples with missing outcome data -----------------------------------
n_samples_current <- get_n_samples(data)
logger_message(
paste0("Pre-processing: ", n_samples_current, " samples were initially available."),
indent = message_indent,
verbose = verbose
)
# Remove all samples with missing outcome data
data <- filter_missing_outcome(data = data, is_validation = FALSE)
if (is_empty(data)) ..error_data_set_has_no_outcome()
n_samples_remain <- get_n_samples(data)
n_samples_removed <- n_samples_current - n_samples_remain
logger_message(
paste0(
"Pre-processing: ", n_samples_removed,
" samples were removed because of missing outcome data. ",
n_samples_remain, " samples remain."
),
indent = message_indent,
verbose = verbose
)
#Remove features with a large fraction of missing values ---------------------
n_features_current <- get_n_features(data)
logger_message(
paste0("Pre-processing: ", n_features_current, " features were initially available."),
indent = message_indent,
verbose = verbose
)
# Determine the fraction of missing values
feature_info_list <- add_missing_value_fractions(
cl = cl,
feature_info_list = feature_info_list,
data = data,
threshold = settings$prep$feature_max_fraction_missing
)
# Find features that are not missing too many values.
available_features <- get_available_features(feature_info_list = feature_info_list)
# Remove features with a high fraction of missing values
data <- filter_features(data = data, available_features = available_features)
if (!has_feature_data(data)) {
..error(
paste0(
"The provided dataset lacks features with sufficient available values. ",
"Please investigate missing values in the dataset or increase the missingness ",
"threshold by increasing the feature_max_fraction_missing configuration parameter."
),
error_class = "dataset_error"
)
}
# Message how many features were removed
logger_message(
paste0(
"Pre-processing: ", n_features_current - length(available_features),
" features were removed because of a high fraction of missing values. ",
length(available_features), " features remain."
),
indent = message_indent,
verbose = verbose
)
n_samples_current <- n_samples_remain
# Remove samples with a large fraction of missing values ---------------------
data <- filter_bad_samples(
data = data,
threshold = settings$prep$sample_max_fraction_missing
)
if (is_empty(data)) {
..error(
paste0(
"The provided dataset lacks samples with sufficient available feature values. ",
"Please investigate missing values in the dataset or increase the missingness ",
"threshold by increasing the sample_max_fraction_missing configuration parameter."
),
error_class = "dataset_error"
)
}
# Message how many samples were removed
n_samples_remain <- get_n_samples(data)
logger_message(
paste0(
"Pre-processing: ", n_samples_current - n_samples_remain,
" samples were removed because of missing feature data. ",
n_samples_remain, " samples remain."
),
indent = message_indent,
verbose = verbose
)
n_features_current <- length(available_features)
# Remove invariant features --------------------------------------------------
# Filter features that are invariant.
feature_info_list <- find_invariant_features(
cl = cl,
feature_info_list = feature_info_list,
data = data
)
# Find available features.
available_features <- get_available_features(feature_info_list = feature_info_list)
# Remove invariant features from the data
data <- filter_features(data = data, available_features = available_features)
if (!has_feature_data(data)) {
..error(
paste0(
"Remaining features in the dataset only have a single value for all samples ",
"and cannot be used for training."
),
error_class = "dataset_error"
)
}
# Message number of features removed by the no-variance filter.
logger_message(
paste0(
"Pre-processing: ", n_features_current - length(available_features),
" features were removed due to invariance. ",
length(available_features), " features remain."
),
indent = message_indent,
verbose = verbose
)
# Add feature distribution data ----------------------------------------------
logger_message(
paste0("Pre-processing: Adding value distribution statistics to features."),
indent = message_indent,
verbose = verbose
)
# Add feature distribution data
feature_info_list <- compute_feature_distribution_data(
cl = cl,
feature_info_list = feature_info_list,
data = data
)
# Transform features ---------------------------------------------------------
logger_message(
"Pre-processing: Performing transformations to normalise feature value distributions.",
indent = message_indent,
verbose = verbose && settings$prep$transform_method != "none"
)
# Add skeletons to the feature information list.
feature_info_list <- create_transformation_parameter_skeleton(
feature_info_list = feature_info_list,
transformation_method = settings$prep$transform_method,
transformation_optimisation_criterion = settings$prep$transformation_optimisation_criterion,
transformation_gof_p_value = settings$prep$transformation_gof_test_p_value
)
# Add transformation parameters to the feature information list
feature_info_list <- add_transformation_parameters(
cl = cl,
feature_info_list = feature_info_list,
data = data,
verbose = verbose
)
# Apply transformation.
data <- transform_features(
data = data,
feature_info_list = feature_info_list
)
logger_message(
"Pre-processing: Feature distributions have been transformed for normalisation.",
indent = message_indent,
verbose = verbose & settings$prep$transform_method != "none"
)
# Remove low-variance features -----------------------------------------------
if ("low_variance" %in% settings$prep$filter_method) {
n_features_current <- length(available_features)
# Filter features that are invariant.
feature_info_list <- find_low_variance_features(
cl = cl,
feature_info_list = feature_info_list,
data = data,
settings = settings
)
# Check available features.
available_features <- get_available_features(feature_info_list = feature_info_list)
# Remove invariant features from the data
data <- filter_features(data = data, available_features = available_features)
if (!has_feature_data(data)) {
..error(
paste0(
"Remaining features in the dataset have a variance that is lower than the threshold ",
"and were therefore all removed. Please investigate your data, or increase the threshold ",
"through the low_var_minimum_variance_threshold configuration parameter."
),
error_class = "dataset_error"
)
}
# Message number of features removed by the low-variance filter.
logger_message(
paste0(
"Pre-processing: ", n_features_current - length(available_features),
" features were removed due to low variance. ",
length(available_features), " features remain."
),
indent = message_indent,
verbose = verbose
)
}
# Normalise features ---------------------------------------------------------
logger_message(
"Pre-processing: Extracting normalisation parameters from feature data.",
indent = message_indent,
verbose = verbose && settings$prep$normalisation_method != "none"
)
# Add skeletons to the feature information list.
feature_info_list <- create_normalisation_parameter_skeleton(
feature_info_list = feature_info_list,
normalisation_method = settings$prep$normalisation_method
)
# Add normalisation parameters to the feature information list.
feature_info_list <- add_normalisation_parameters(
cl = cl,
feature_info_list = feature_info_list,
data = data,
verbose = verbose
)
# Apply normalisation to data before clustering
data <- normalise_features(
data = data,
feature_info_list = feature_info_list
)
logger_message(
"Pre-processing: Feature data were normalised.",
indent = message_indent,
verbose = verbose && settings$prep$normalisation_method != "none"
)
# Batch normalise features ---------------------------------------------------
logger_message(
"Pre-processing: Extracting batch normalisation parameters from feature data.",
indent = message_indent,
verbose = verbose && settings$prep$batch_normalisation_method != "none"
)
# Check that assumptions for batch normalisation are fulfilled.
.check_batch_normalisation_assumptions(
data = data,
normalisation_method = settings$prep$batch_normalisation_method
)
# Add batch normalisation skeletons.
feature_info_list <- create_batch_normalisation_parameter_skeleton(
feature_info_list = feature_info_list,
normalisation_method = settings$prep$batch_normalisation_method
)
# Add batch normalisation parameters to the feature information list.
feature_info_list <- add_batch_normalisation_parameters(
cl = cl,
feature_info_list = feature_info_list,
data = data,
verbose = verbose
)
# Batch-normalise feature values
data <- batch_normalise_features(
data = data,
feature_info_list = feature_info_list
)
logger_message(
"Pre-processing: Feature data were batch-normalised.",
indent = message_indent,
verbose = verbose && settings$prep$batch_normalisation_method != "none"
)
# Remove non-robust features -------------------------------------------------
if ("robustness" %in% settings$prep$filter_method) {
n_features_current <- length(available_features)
# Filter features that are not robust
feature_info_list <- find_non_robust_features(
cl = cl,
feature_info_list = feature_info_list,
data = data,
settings = settings
)
available_features <- get_available_features(feature_info_list = feature_info_list)
# Remove non-robust features from the data
data <- filter_features(data = data, available_features = available_features)
if (!has_feature_data(data)) {
..error(
paste0(
"Remaining features in the dataset have a robustness that is lower than the threshold ",
"and were therefore all removed. Please investigate your data, or decrease the threshold ",
"through the robustness_threshold_value configuration parameter."
),
error_class = "dataset_error"
)
}
# Message number of features removed by the robustness filter.
logger_message(
paste0(
"Pre-processing: ", n_features_current - length(available_features),
" features were removed due to low robustness. ",
length(available_features), " features remain."
),
indent = message_indent,
verbose = verbose
)
}
# Remove unimportant features ------------------------------------------------
if ("univariate_test" %in% settings$prep$filter_method) {
n_features_current <- length(available_features)
# Filter features that are not relevant
feature_info_list <- find_unimportant_features(
cl = cl,
feature_info_list = feature_info_list,
data = data,
settings = settings
)
available_features <- get_available_features(feature_info_list = feature_info_list)
# Remove unimportant features from the data
data <- filter_features(data = data, available_features = available_features)
if (!has_feature_data(data)) {
..error(
paste0(
"Remaining features in the dataset have a p-value that is higher than the threshold ",
"and were therefore all removed. Please investigate your data, or increase the threshold ",
"through the univariate_test_threshold configuration parameter."
),
error_class = "dataset_error"
)
}
# Message number of features removed by the importance filter.
logger_message(
paste0(
"Pre-processing: ", n_features_current - length(available_features),
" features were removed due to low importance. ",
length(available_features), " features remain."
),
indent = message_indent,
verbose = verbose
)
}
# Impute missing values ------------------------------------------------------
logger_message(
"Pre-processing: Adding imputation information to features.",
indent = message_indent,
verbose = verbose
)
# Add imputation skeletons.
feature_info_list <- create_imputation_parameter_skeleton(
feature_info_list = feature_info_list,
imputation_method = settings$prep$imputation_method
)
# Add imputation info
feature_info_list <- add_imputation_info(
cl = cl,
feature_info_list = feature_info_list,
data = data,
verbose = verbose
)
# Impute features with censored data prior to clustering
data <- impute_features(
data = data,
feature_info_list = feature_info_list
)
# Cluster features -----------------------------------------------------------
logger_message(
"Pre-processing: Starting clustering of redundant features",
indent = message_indent,
verbose = verbose && settings$prep$cluster_method != "none"
)
# Determine the number of features prior to clustering.
n_features_current <- length(get_available_features(feature_info_list = feature_info_list))
# Add clustering skeletons.
feature_info_list <- create_cluster_parameter_skeleton(
feature_info_list = feature_info_list,
cluster_method = settings$prep$cluster_method,
cluster_linkage = settings$prep$cluster_linkage,
cluster_cut_method = settings$prep$cluster_cut_method,
cluster_similarity_threshold = settings$prep$cluster_similarity_threshold,
cluster_similarity_metric = settings$prep$cluster_similarity_metric,
cluster_representation_method = settings$prep$cluster_representation_method
)
# Extract clustering information
feature_info_list <- add_cluster_info(
cl = cl,
feature_info_list = feature_info_list,
data = data,
message_indent = message_indent + 1L,
verbose = verbose
)
# Build cluster table.
cluster_table <- .create_clustering_table(feature_info_list = feature_info_list)
# Further summarise the clusters by grouping.
cluster_table <- cluster_table[, list("cluster_size" = .N), by = "cluster_name"]
logger_message(
paste0(
nrow(cluster_table),
ifelse(nrow(cluster_table) == 1L, " feature cluster was", " feature clusters were"),
" created from ", n_features_current,
ifelse(n_features_current == 1L, " feature. ", " features. "),
sum(cluster_table$cluster_size > 1L),
ifelse(sum(cluster_table$cluster_size > 1L) == 1L, " cluster contains", " clusters contain"),
" more than one feature. The remaining ",
sum(cluster_table$cluster_size == 1L),
ifelse(sum(cluster_table$cluster_size == 1L) == 1L, " cluster is", " clusters are"),
" singular."
),
indent = message_indent + 1L,
verbose = verbose && settings$prep$cluster_method != "none"
)
# Add required features
feature_info_list <- add_required_features(feature_info_list = feature_info_list)
# Filter features that are not required from the list
feature_info_list <- trim_unused_features_from_list(feature_info_list = feature_info_list)
# Return list of featureInfo objects
return(feature_info_list)
}
combine_feature_info_list <- function(
preferred = NULL,
custom = NULL,
generic = NULL
) {
# Suppress NOTES due to non-standard evaluation in data.table
name <- present <- list_name <- complete <- NULL
# Get all features.
feature_names <- unique(c(
names(preferred),
names(custom),
names(generic)
))
# Identify which features appear where.
data <- mapply(
FUN = function(x, x_name, feature_names) {
# Default dataset.
data <- data.table::data.table(
"list_name" = x_name,
"name" = feature_names,
"present" = FALSE,
"complete" = FALSE
)
# Mark feature names that are present in the current dataset.
data[name %in% names(x), "present" := TRUE]
# Check whether data are present, are complete.
data[
present == TRUE,
"complete" := feature_info_complete(object = x[[name]]),
by = "name"
]
return(data)
},
x = list(
"preferred" = preferred,
"custom" = custom,
"generic" = generic
),
x_name = c("preferred", "custom", "generic"),
MoreArgs = list("feature_names" = feature_names),
SIMPLIFY = FALSE
)
# Combine list.
data <- data.table::rbindlist(data)
# Start new feature list.
new_feature_list <- NULL
# Preference to get features with complete information first from the
# preferred set.
selected_feature_names <- data[list_name == "preferred" & complete == TRUE]$name
# Add to feature list and remove from set of features.
if (length(selected_feature_names) > 0L) {
new_feature_list <- c(new_feature_list, preferred[selected_feature_names])
feature_names <- setdiff(feature_names, selected_feature_names)
}
# Then, preference to get complete information from the custom set.
selected_feature_names <- data[name %in% feature_names & list_name == "custom" & complete == TRUE, ]$name
# Add to feature list and remove from set of features.
if (length(selected_feature_names) > 0L) {
new_feature_list <- c(new_feature_list, custom[selected_feature_names])
feature_names <- setdiff(feature_names, selected_feature_names)
}
# Then, preference to get incomplete information first from the preferred set.
selected_feature_names <- data[name %in% feature_names & list_name == "preferred" & present == TRUE, ]$name
# Add to feature list and remove from set of features.
if (length(selected_feature_names) > 0L) {
new_feature_list <- c(new_feature_list, preferred[selected_feature_names])
feature_names <- setdiff(feature_names, selected_feature_names)
}
# Then, preference to get incomplete information first from the custom set.
selected_feature_names <- data[name %in% feature_names & list_name == "custom" & present == TRUE, ]$name
# Add to feature list and remove from set of features.
if (length(selected_feature_names) > 0L) {
new_feature_list <- c(new_feature_list, custom[selected_feature_names])
feature_names <- setdiff(feature_names, selected_feature_names)
}
# Then, preference to get incomplete information first from the generic set.
selected_feature_names <- data[name %in% feature_names & list_name == "generic" & present == TRUE, ]$name
# Add to feature list and remove from set of features.
if (length(selected_feature_names) > 0L) {
new_feature_list <- c(new_feature_list, generic[selected_feature_names])
feature_names <- setdiff(feature_names, selected_feature_names)
}
return(new_feature_list)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.