diff --git a/.travis.yml b/.travis.yml index 74f70875..426fc9cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,5 +34,4 @@ env: global: - _R_CHECK_FORCE_SUGGESTS_=false - MAKEFLAGS="-j 2" - - BUILD_PKGDOWN=true - _R_CHECK_TESTS_NLINES_=0 diff --git a/DESCRIPTION b/DESCRIPTION index befe51a1..ad4fb0ad 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -25,6 +25,7 @@ BugReports: https://github.com/mlr-org/mlr3featsel/issues Depends: R (>= 3.1.0) Imports: + backports, checkmate, data.table, mlr3, @@ -57,7 +58,8 @@ NeedsCompilation: no Roxygen: list(markdown = TRUE) RoxygenNote: 6.1.1 Collate: - 'Filter.R' + 'mlr_filters.R' + 'FilterResult.R' 'FilterAUC.R' 'FilterCMIM.R' 'FilterDISR.R' @@ -74,7 +76,7 @@ Collate: 'FilterSymmetricalUncertainty.R' 'FilterVariableImportance.R' 'FilterVariance.R' + 'helper_expectations.R' 'helpers.R' - 'mlr_filters.R' 'reexports.R' 'zzz.R' diff --git a/NAMESPACE b/NAMESPACE index c126952d..32aa28f1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,8 +1,7 @@ # Generated by roxygen2: do not edit by hand -S3method(as.data.table,DictionaryFilter) -S3method(as.data.table,Filter) -export(Filter) +S3method(as.data.table,DictionaryFilterResult) +S3method(as.data.table,FilterResult) export(FilterAUC) export(FilterCMIM) export(FilterDISR) @@ -16,6 +15,7 @@ export(FilterMIM) export(FilterMRMR) export(FilterNJMIM) export(FilterRankCorrelation) +export(FilterResult) export(FilterSymmetricalUncertainty) export(FilterVariableImportance) export(FilterVariance) diff --git a/R/FilterAUC.R b/R/FilterAUC.R index 94e78b37..2a92e2c7 100644 --- a/R/FilterAUC.R +++ b/R/FilterAUC.R @@ -1,7 +1,7 @@ #' @title AUC Filter #' #' @aliases mlr_filters_auc -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("sonar") #' filter = FilterAUC$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterAUC = R6Class("FilterAUC", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterAUC = R6Class("FilterAUC", inherit = FilterResult, public = list( initialize = function(id = "auc") { super$initialize( @@ -37,3 +37,5 @@ FilterAUC = R6Class("FilterAUC", inherit = Filter, } ) ) + +register_filter("auc", FilterAUC) diff --git a/R/FilterCMIM.R b/R/FilterCMIM.R index 4fb8402e..f74183d5 100644 --- a/R/FilterCMIM.R +++ b/R/FilterCMIM.R @@ -1,7 +1,7 @@ #' @title Minimal Conditional Mutual Information Filter #' #' @aliases mlr_filters_cmim -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterCMIM$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterCMIM = R6Class("FilterCMIM", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterCMIM = R6Class("FilterCMIM", inherit = FilterResult, public = list( initialize = function(id = "cmim") { super$initialize( @@ -35,3 +35,5 @@ FilterCMIM = R6Class("FilterCMIM", inherit = Filter, } ) ) + +register_filter("cmim", FilterCMIM) diff --git a/R/FilterDISR.R b/R/FilterDISR.R index 2c35aa65..95ae8083 100644 --- a/R/FilterDISR.R +++ b/R/FilterDISR.R @@ -1,7 +1,7 @@ #' @title Double Input Symmetrical Relevance Filter #' #' @aliases mlr_filters_disr -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterDISR$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterDISR = R6Class("FilterDISR", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterDISR = R6Class("FilterDISR", inherit = FilterResult, public = list( initialize = function(id = "disr") { super$initialize( @@ -35,3 +35,5 @@ FilterDISR = R6Class("FilterDISR", inherit = Filter, } ) ) + +register_filter("disr", FilterDISR) diff --git a/R/FilterGainRatio.R b/R/FilterGainRatio.R index 57c2686c..d0983da9 100644 --- a/R/FilterGainRatio.R +++ b/R/FilterGainRatio.R @@ -1,7 +1,7 @@ #' @title Gain Ratio Filter #' #' @aliases mlr_filters_gain_ratio -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -15,8 +15,8 @@ #' task = mlr3::mlr_tasks$get("sonar") #' filter = FilterGainRatio$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterGainRatio = R6Class("FilterGainRatio", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterGainRatio = R6Class("FilterGainRatio", inherit = FilterResult, public = list( initialize = function(id = "gain_ratio") { super$initialize( @@ -38,3 +38,5 @@ FilterGainRatio = R6Class("FilterGainRatio", inherit = Filter, } ) ) + +register_filter("gain_ratio", FilterGainRatio) diff --git a/R/FilterInformationGain.R b/R/FilterInformationGain.R index 9e746eab..596c5dd4 100644 --- a/R/FilterInformationGain.R +++ b/R/FilterInformationGain.R @@ -1,7 +1,7 @@ #' @title Information Gain Filter #' #' @aliases mlr_filters_information_gain -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -15,8 +15,8 @@ #' task = mlr3::mlr_tasks$get("sonar") #' filter = FilterInformationGain$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterInformationGain = R6Class("FilterInformationGain", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterInformationGain = R6Class("FilterInformationGain", inherit = FilterResult, public = list( initialize = function(id = "information_gain") { super$initialize( @@ -37,3 +37,5 @@ FilterInformationGain = R6Class("FilterInformationGain", inherit = Filter, } ) ) + +register_filter("information_gain", FilterInformationGain) diff --git a/R/FilterJMI.R b/R/FilterJMI.R index 22e00321..f005f829 100644 --- a/R/FilterJMI.R +++ b/R/FilterJMI.R @@ -1,7 +1,7 @@ #' @title Joint Mutual Information Filter #' #' @aliases mlr_filters_jmi -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterJMI$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterJMI = R6Class("FilterJMI", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterJMI = R6Class("FilterJMI", inherit = FilterResult, public = list( initialize = function(id = "jmi") { super$initialize( @@ -35,3 +35,5 @@ FilterJMI = R6Class("FilterJMI", inherit = Filter, } ) ) + +register_filter("jmi", FilterJMI) diff --git a/R/FilterJMIM.R b/R/FilterJMIM.R index f1f13a62..bdee1e20 100644 --- a/R/FilterJMIM.R +++ b/R/FilterJMIM.R @@ -1,7 +1,7 @@ #' @title Minimal Joint Mutual Information Maximisation Filter #' #' @aliases mlr_filters_jmim -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterJMIM$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterJMIM = R6Class("FilterJMIM", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterJMIM = R6Class("FilterJMIM", inherit = FilterResult, public = list( initialize = function(id = "jmim") { super$initialize( diff --git a/R/FilterKruskalTest.R b/R/FilterKruskalTest.R index 8e0128a7..aae22424 100644 --- a/R/FilterKruskalTest.R +++ b/R/FilterKruskalTest.R @@ -1,7 +1,7 @@ #' @title Kruskal-Wallis Test Filter #' #' @aliases mlr_filters_kruskal_test -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterKruskalTest$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterKruskalTest = R6Class("FilterKruskalTest", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterKruskalTest = R6Class("FilterKruskalTest", inherit = FilterResult, public = list( initialize = function(id = "kruskal_test") { super$initialize( @@ -38,3 +38,5 @@ FilterKruskalTest = R6Class("FilterKruskalTest", inherit = Filter, } ) ) + +register_filter("kruskal_test", FilterKruskalTest) diff --git a/R/FilterLinearCorrelation.R b/R/FilterLinearCorrelation.R index 909863e8..d860968f 100644 --- a/R/FilterLinearCorrelation.R +++ b/R/FilterLinearCorrelation.R @@ -1,7 +1,7 @@ #' @title Linear Correlation Filter #' #' @aliases mlr_filters_linear_correlation -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("mtcars") #' filter = FilterLinearCorrelation$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterLinearCorrelation = R6Class("FilterLinearCorrelation", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterLinearCorrelation = R6Class("FilterLinearCorrelation", inherit = FilterResult, public = list( initialize = function(id = "linear_correlation") { super$initialize( @@ -37,3 +37,5 @@ FilterLinearCorrelation = R6Class("FilterLinearCorrelation", inherit = Filter, } ) ) + +register_filter("linear_correlation", FilterLinearCorrelation) diff --git a/R/FilterMIM.R b/R/FilterMIM.R index 13d0f8b0..c4f6a90b 100644 --- a/R/FilterMIM.R +++ b/R/FilterMIM.R @@ -1,7 +1,7 @@ #' @title Conditional Mutual Information Based Feature Selection Filter #' #' @aliases mlr_filters_mim -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterMIM$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterMIM = R6Class("FilterMIM", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterMIM = R6Class("FilterMIM", inherit = FilterResult, public = list( initialize = function(id = "mim") { super$initialize( @@ -35,3 +35,5 @@ FilterMIM = R6Class("FilterMIM", inherit = Filter, } ) ) + +register_filter("mim", FilterMIM) diff --git a/R/FilterMRMR.R b/R/FilterMRMR.R index 3f94f9d2..f44ab1fd 100644 --- a/R/FilterMRMR.R +++ b/R/FilterMRMR.R @@ -1,7 +1,7 @@ #' @title Minimum redundancy maximal relevancy filter #' #' @aliases mlr_filters_MRMR -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -15,7 +15,7 @@ #' filter = FilterMRMR$new() #' filter$calculate(task) #' head(as.data.table(filter), 3) -FilterMRMR = R6Class("FilterMRMR", inherit = Filter, +FilterMRMR = R6Class("FilterMRMR", inherit = FilterResult, public = list( initialize = function(id = "MRMR") { super$initialize( diff --git a/R/FilterNJMIM.R b/R/FilterNJMIM.R index 7cd04409..61e7a543 100644 --- a/R/FilterNJMIM.R +++ b/R/FilterNJMIM.R @@ -1,7 +1,7 @@ #' @title Minimal Normalised Joint Mutual Information Maximisation Filter #' #' @aliases mlr_filters_njmim -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("iris") #' filter = FilterNJMIM$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterNJMIM = R6Class("FilterNJMIM", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterNJMIM = R6Class("FilterNJMIM", inherit = FilterResult, public = list( initialize = function(id = "njmim") { super$initialize( @@ -35,3 +35,5 @@ FilterNJMIM = R6Class("FilterNJMIM", inherit = Filter, } ) ) + +register_filter("njmim", FilterNJMIM) diff --git a/R/FilterRankCorrelation.R b/R/FilterRankCorrelation.R index 5ad78410..f2759f0d 100644 --- a/R/FilterRankCorrelation.R +++ b/R/FilterRankCorrelation.R @@ -1,7 +1,7 @@ #' @title Rank Correlation Filter #' #' @aliases mlr_filters_rank_correlation -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,8 +14,8 @@ #' task = mlr3::mlr_tasks$get("mtcars") #' filter = FilterRankCorrelation$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterRankCorrelation = R6Class("FilterRankCorrelation", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterRankCorrelation = R6Class("FilterRankCorrelation", inherit = FilterResult, public = list( initialize = function(id = "rank_correlation") { super$initialize( @@ -37,3 +37,5 @@ FilterRankCorrelation = R6Class("FilterRankCorrelation", inherit = Filter, } ) ) + +register_filter("rank_correlation", FilterRankCorrelation) diff --git a/R/Filter.R b/R/FilterResult.R similarity index 84% rename from R/Filter.R rename to R/FilterResult.R index bc01ecba..3310aa50 100644 --- a/R/Filter.R +++ b/R/FilterResult.R @@ -9,7 +9,7 @@ #' #' @section Construction: #' ``` -#' f = Filter$new(id, task_type, param_set, param_vals, feature_types, packages) +#' f = FilterResult$new(id, task_type, param_set, param_vals, feature_types, packages) #' ``` #' #' * `id` :: `character(1)`\cr @@ -80,7 +80,7 @@ #' #' @family Filter #' @export -Filter = R6Class("Filter", +FilterResult = R6Class("FilterResult", public = list( id = NULL, task_type = NULL, @@ -100,10 +100,18 @@ Filter = R6Class("Filter", self$packages = assert_character(packages, any.missing = FALSE, unique = TRUE) }, + format = function() { + sprintf("<%s:%s>", class(self)[1L], self$id) + }, + + print = function() { + filter_print(self) + }, + calculate = function(task) { assert_task(task, feature_types = self$feature_types, task_properties = self$task_properties) - assert_filter(self, task) + assert_filter_result(self, task) require_namespaces(self$packages) fn = task$feature_names @@ -111,12 +119,17 @@ Filter = R6Class("Filter", assert_numeric(fv, len = length(fn), any.missing = FALSE) assert_names(names(fv), permutation.of = fn) - # shuffle fv before sort to generate a random order of tied observations - self$scores = sort(shuffle(fv), decreasing = TRUE, na.last = TRUE) + self$scores = data.table(score = fv, feature = fn, method = self$id)[order(method, -score)] invisible(self) }, + combine = function(fr) { + assert_filter_result(fr) + self$scores = rbindlist(list(self$scores, fr$scores)) + invisible(self) + }, + filter_abs = function(task, abs) { assert_task(task) assert_count(abs) @@ -146,10 +159,18 @@ filter_n = function(self, task, n) { } #' @export -as.data.table.Filter = function(x, ...) { +as.data.table.FilterResult = function(x, ...) { fv = x$scores if (is.null(fv)) { stopf("No filter data available") } - enframe(x$scores) + return(fv) +} + +filter_print = function(self) { + catf(format(self)) + catf(str_indent("Task Types:", self$task_type)) + catf(str_indent("Task Properties:", self$task_properties)) + catf(str_indent("Packages:", self$packages)) + catf(str_indent("Feature types:", self$feature_types)) } diff --git a/R/FilterSymmetricalUncertainty.R b/R/FilterSymmetricalUncertainty.R index ee42f5ab..0bd338af 100644 --- a/R/FilterSymmetricalUncertainty.R +++ b/R/FilterSymmetricalUncertainty.R @@ -1,7 +1,7 @@ #' @title Symmetrical Uncertainty Filter #' #' @aliases mlr_filters_symmetrical_uncertainty -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -15,8 +15,8 @@ #' task = mlr3::mlr_tasks$get("sonar") #' filter = FilterSymmetricalUncertainty$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterSymmetricalUncertainty = R6Class("FilterSymmetricalUncertainty", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterSymmetricalUncertainty = R6Class("FilterSymmetricalUncertainty", inherit = FilterResult, public = list( initialize = function(id = "symmetrical_uncertainty") { super$initialize( @@ -38,3 +38,5 @@ FilterSymmetricalUncertainty = R6Class("FilterSymmetricalUncertainty", inherit = } ) ) + +register_filter("symmetrical_uncertainty", FilterSymmetricalUncertainty) diff --git a/R/FilterVariableImportance.R b/R/FilterVariableImportance.R index 83755ed8..d0139158 100644 --- a/R/FilterVariableImportance.R +++ b/R/FilterVariableImportance.R @@ -1,7 +1,7 @@ #' @title Variable Importance Filter #' #' @aliases mlr_filters_variable_importance -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -10,18 +10,18 @@ #' fits the model and uses the importance values as filter scores. #' #' -#' @family Filter +#' @family FilterResult #' @export #' @examples #' task = mlr3::mlr_tasks$get("iris") #' learner = mlr3::mlr_learners$get("classif.rpart") #' filter = FilterVariableImportance$new(learner = learner) #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterVariableImportance = R6Class("FilterVariableImportance", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterVariableImportance = R6Class("FilterVariableImportance", inherit = FilterResult, public = list( - learner = NULL, - initialize = function(id = "variable_importance", learner) { + learner = mlr3::mlr_learners$get("classif.rpart"), + initialize = function(id = "variable_importance", learner = self$learner) { self$learner = assert_learner(learner, properties = "importance") super$initialize( @@ -45,3 +45,5 @@ FilterVariableImportance = R6Class("FilterVariableImportance", inherit = Filter, } ) ) + +register_filter("variable_importance", FilterVariableImportance) diff --git a/R/FilterVariance.R b/R/FilterVariance.R index d033fb1b..c779a339 100644 --- a/R/FilterVariance.R +++ b/R/FilterVariance.R @@ -1,7 +1,7 @@ #' @title Variance Filter #' #' @aliases mlr_filters_variance -#' @format [R6::R6Class] inheriting from [Filter]. +#' @format [R6::R6Class] inheriting from [FilterResult]. #' @include Filter.R #' #' @description @@ -14,10 +14,10 @@ #' task = mlr3::mlr_tasks$get("mtcars") #' filter = FilterVariance$new() #' filter$calculate(task) -#' head(as.data.table(filter), 3) -FilterVariance = R6Class("FilterVariance", inherit = Filter, +#' as.data.table(filter)[1:3] +FilterVariance = R6Class("FilterVariance", inherit = FilterResult, public = list( - initialize = function(id = "FilterVariance", param_vals = list(na.rm = TRUE)) { + initialize = function(id = "variance", param_vals = list(na.rm = TRUE)) { super$initialize( id = id, packages = "stats", @@ -38,3 +38,5 @@ FilterVariance = R6Class("FilterVariance", inherit = Filter, } ) ) + +register_filter("variance", FilterVariance) diff --git a/R/helper_expectations.R b/R/helper_expectations.R new file mode 100644 index 00000000..14e6dc1b --- /dev/null +++ b/R/helper_expectations.R @@ -0,0 +1,21 @@ +expect_filter_result = function(fr) { + + checkmate::expect_r6(fr, "FilterResult", public = c("scores")) + testthat::expect_output(print(fr), "FilterResult") + + checkmate::expect_data_table(fr$scores) + checkmate::expect_names(names(fr$scores), must.include = c("method", "scores")) + + tab = fr$feature_types + checkmate::expect_character(tab) + + tab = fr$packages + checkmate::expect_character(tab) + + tab = fr$task_type + checkmate::expect_character(tab) + + tab = fr$task_properties + checkmate::expect_character(tab) + +} diff --git a/R/helpers.R b/R/helpers.R index 2e3fcc67..6341199d 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -1,5 +1,5 @@ -assert_filter = function(filter, task = NULL) { - filter = cast_from_dict(filter, "Filter", mlr_filters, FALSE)[[1L]] +assert_filter_result = function(filter, task = NULL) { + filter = cast_from_dict(filter, "FilterResult", mlr_filters, FALSE)[[1L]] if (!is.null(task)) { if (task$task_type %nin% filter$task_type) { diff --git a/R/mlr_filters.R b/R/mlr_filters.R index df5b5a5d..12aa0ab2 100644 --- a/R/mlr_filters.R +++ b/R/mlr_filters.R @@ -2,7 +2,7 @@ #' #' @format [R6Class] object #' @description -#' A simple [Dictionary] storing objects of class [Filter]. +#' A simple [Dictionary] storing objects of class [FilterResult]. #' Each Filter has an associated help page, see `mlr_filters_[id]`. #' #' @section Usage: @@ -18,8 +18,8 @@ #' mlr_filters$get("mim") NULL -DictionaryFilter = R6Class("DictionaryFilter", - inherit = Dictionary, +DictionaryFilterResult = R6Class("DictionaryFilterResult", + inherit = mlr3::Dictionary, cloneable = FALSE ) @@ -27,13 +27,41 @@ DictionaryFilter = R6Class("DictionaryFilter", mlr_filters = NULL #' @export -as.data.table.DictionaryFilter = function(x, ...) { - setkeyv(map_dtr(x$keys(), function(id) { - if (length(x$required_args(id)) > 0L) { - return(list(id = id, packages = list(NA_character_), feature_types = list(NA_character_), task_type = list(NA_character_))) - } - l = x$get(id) - list(id = id, packages = list(l$packages), feature_types = list(l$feature_types), - task_type = list(l$task_type)) - }), "id")[] +as.data.table.DictionaryFilterResult = function(x, ...) { + setkeyv(map_dtr(x$keys(), function(key) { + l = x$get(key) + list( + key = key, + task_type = list(l$task_type), + task_properties = list(l$task_properties), + param_set = list(l$param_set), + feature_types = list(l$feature_types), + packages = list(l$packages) + ) + }), "key")[] } + +# We would like to have the filters in the "mlr_filters" Dictionary, but adding +# them at build time is apparently not a good idea. On the other hand we would +# like to register filters near their definition to prevent confusing +# dependencies throughout the codebase. Therefore we register the filters using +# "register_filter()" below their definition and call +# "publish_registered_filters()" in .onLoad. (adapted from mlr3pipelines) +mlr_filter_register = new.env(parent = emptyenv()) + +# nocov start +register_filter = function(key, value) { + m = match.call(expand.dots = FALSE) + mlr_filter_register[[key]] = m +} + +publish_registered_filters = function() { + mlr_filters <<- DictionaryFilterResult$new() + + for (registercall in as.list(mlr_filter_register)) { + registercall[[1]] = quote(mlr_filters$add) + eval(registercall, envir = parent.env(environment())) + } + rm("mlr_filter_register", envir = parent.env(environment())) +} +# nocov end diff --git a/R/zzz.R b/R/zzz.R index 86af682d..c5ce8f0d 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -8,23 +8,12 @@ "_PACKAGE" .onLoad = function(libname, pkgname) { - # nocov start - mlr_filters <<- DictionaryFilter$new() + backports::import(pkgname) + + # this is to silence note "publish_registered_filters: no visible binding for global variable ‘mlr_filter_register’" during R CMD check + utils::globalVariables("mlr_filter_register") + + publish_registered_filters() # create and fill mlr_filters Dictionary - mlr_filters$add("auc", FilterAUC) - mlr_filters$add("cmim", FilterCMIM) - mlr_filters$add("disr", FilterDISR) - mlr_filters$add("gain_ratio", FilterGainRatio) - mlr_filters$add("information_gain", FilterInformationGain) - mlr_filters$add("jmi", FilterJMI) - mlr_filters$add("jmim", FilterJMIM) - mlr_filters$add("kruskal_test", FilterKruskalTest) - mlr_filters$add("linear_correlation", FilterLinearCorrelation) - mlr_filters$add("mim", FilterMIM) - mlr_filters$add("njmim", FilterNJMIM) - mlr_filters$add("rank_correlation", FilterRankCorrelation) - mlr_filters$add("symmetrical_uncertainty", FilterSymmetricalUncertainty) - mlr_filters$add("variable_importance", FilterVariableImportance, required_args = "learner") - mlr_filters$add("variance", FilterVariance) } # nocov end diff --git a/README.Rmd b/README.Rmd index 8b576af8..0b1ef252 100644 --- a/README.Rmd +++ b/README.Rmd @@ -43,7 +43,9 @@ tab[, task_type := sapply(task_type, function(x) paste(capitalize(x), collapse = tab[, feature_types := sapply(feature_types, function(x) paste(capitalize(x), collapse = ", "))] setorderv(tab, "task_type") tab[, packages := sprintf("*%s*", packages)] -setnames(tab, old = c("packages", "feature_types", "task_type", "id"), new = c("Package", "Features", "Task", "Name")) +setnames(tab, + old = c("key", "task_type", "task_properties", "param_set", "feature_types", "packages"), + new = c("Name", "Task Type", "Task Properties", "Parameter Set", "Feature Types", "Package")) knitr::kable(tab, escape = F, format = "markdown") ``` diff --git a/README.md b/README.md index c80160a7..9d6ff1c1 100644 --- a/README.md +++ b/README.md @@ -32,23 +32,22 @@ remotes::install_github("mlr-org/mlr3featsel") ### Generic Filters -| Name | Package | Features | Task | -| :----------------------- | :-------------- | :-------------------------------- | :------------- | -| auc | *Metrics* | Integer, Numeric | Classif | -| disr | *praznik* | Integer, Numeric, Factor, Ordered | Classif | -| jmi | *praznik* | Integer, Numeric, Factor, Ordered | Classif | -| jmim | *praznik* | Integer, Numeric, Factor, Ordered | Classif | -| kruskal\_test | *stats* | Integer, Numeric | Classif | -| mim | *praznik* | Integer, Numeric, Factor, Ordered | Classif | -| njmim | *praznik* | Integer, Numeric, Factor, Ordered | Classif | -| cmim | *praznik* | Integer, Numeric, Factor, Ordered | Classif & Regr | -| gain\_ratio | *FSelectorRcpp* | Integer, Numeric, Factor, Ordered | Classif & Regr | -| information\_gain | *FSelectorRcpp* | Integer, Numeric, Factor, Ordered | Classif & Regr | -| symmetrical\_uncertainty | *FSelectorRcpp* | Integer, Numeric, Factor, Ordered | Classif & Regr | -| variance | *stats* | Integer, Numeric | Classif & Regr | -| variable\_importance | *NA* | NA | NA | -| linear\_correlation | *stats* | Integer, Numeric | Regr | -| rank\_correlation | *stats* | Integer, Numeric | Regr | +| Name | Task Type | Task Properties | Parameter Set | Feature Types | Package | +| :----------------------- | :------------- | :-------------- | :------------ | :---------------------------------------------------- | :-------------- | +| auc | Classif | twoclass | | Integer, Numeric | *Metrics* | +| disr | Classif | character(0) | | Integer, Numeric, Factor, Ordered | *praznik* | +| jmi | Classif | character(0) | | Integer, Numeric, Factor, Ordered | *praznik* | +| kruskal\_test | Classif | character(0) | | Integer, Numeric | *stats* | +| mim | Classif | character(0) | | Integer, Numeric, Factor, Ordered | *praznik* | +| njmim | Classif | character(0) | | Integer, Numeric, Factor, Ordered | *praznik* | +| variable\_importance | Classif | character(0) | | Logical, Integer, Numeric, Character, Factor, Ordered | *rpart* | +| cmim | Classif & Regr | character(0) | | Integer, Numeric, Factor, Ordered | *praznik* | +| gain\_ratio | Classif & Regr | character(0) | | Integer, Numeric, Factor, Ordered | *FSelectorRcpp* | +| information\_gain | Classif & Regr | character(0) | | Integer, Numeric, Factor, Ordered | *FSelectorRcpp* | +| symmetrical\_uncertainty | Classif & Regr | character(0) | | Integer, Numeric, Factor, Ordered | *FSelectorRcpp* | +| variance | Classif & Regr | character(0) | | Integer, Numeric | *stats* | +| linear\_correlation | Regr | character(0) | | Integer, Numeric | *stats* | +| rank\_correlation | Regr | character(0) | | Integer, Numeric | *stats* | ### Embedded Filters @@ -77,16 +76,16 @@ filter = FilterVariableImportance$new(learner = lrn) filter$calculate(task) ``` - ## INFO [15:36:19.726] Training learner 'classif.ranger' on task 'iris' ... + ## INFO [13:41:25.182] Training learner 'classif.ranger' on task 'iris' ... ``` r head(as.data.table(filter), 3) ``` - ## name value - ## 1: Petal.Width 44.300510 - ## 2: Petal.Length 42.870670 - ## 3: Sepal.Length 9.786203 + ## score feature method + ## 1: 43.67502 Petal.Length variable_importance + ## 2: 42.75024 Petal.Width variable_importance + ## 3: 10.37421 Sepal.Length variable_importance ## “Wrapper” Methods diff --git a/man/FilterAUC.Rd b/man/FilterAUC.Rd index 7595141a..3abb8d76 100644 --- a/man/FilterAUC.Rd +++ b/man/FilterAUC.Rd @@ -5,7 +5,7 @@ \alias{FilterAUC} \alias{mlr_filters_auc} \title{AUC Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterAUC } @@ -17,7 +17,7 @@ Calls \code{\link[Metrics:auc]{Metrics::auc()}}, and scores with the absolute va task = mlr3::mlr_tasks$get("sonar") filter = FilterAUC$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterCMIM}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterCMIM}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterCMIM.Rd b/man/FilterCMIM.Rd index 3eb246a7..44dcafc4 100644 --- a/man/FilterCMIM.Rd +++ b/man/FilterCMIM.Rd @@ -5,7 +5,7 @@ \alias{FilterCMIM} \alias{mlr_filters_cmim} \title{Minimal Conditional Mutual Information Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterCMIM } @@ -17,7 +17,7 @@ Calls \code{\link[praznik:CMIM]{praznik::CMIM()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterCMIM$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterDISR.Rd b/man/FilterDISR.Rd index c065acc0..b8515b31 100644 --- a/man/FilterDISR.Rd +++ b/man/FilterDISR.Rd @@ -5,7 +5,7 @@ \alias{FilterDISR} \alias{mlr_filters_disr} \title{Double Input Symmetrical Relevance Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterDISR } @@ -17,7 +17,7 @@ Calls \code{\link[praznik:DISR]{praznik::DISR()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterDISR$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterGainRatio.Rd b/man/FilterGainRatio.Rd index 68a7acfa..62957005 100644 --- a/man/FilterGainRatio.Rd +++ b/man/FilterGainRatio.Rd @@ -5,7 +5,7 @@ \alias{FilterGainRatio} \alias{mlr_filters_gain_ratio} \title{Gain Ratio Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterGainRatio } @@ -18,7 +18,7 @@ The target variable of regression tasks is automatically binned (argument \code{ task = mlr3::mlr_tasks$get("sonar") filter = FilterGainRatio$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -30,10 +30,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterInformationGain.Rd b/man/FilterInformationGain.Rd index 7ef6d9d3..82dd08f5 100644 --- a/man/FilterInformationGain.Rd +++ b/man/FilterInformationGain.Rd @@ -5,7 +5,7 @@ \alias{FilterInformationGain} \alias{mlr_filters_information_gain} \title{Information Gain Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterInformationGain } @@ -18,7 +18,7 @@ The target variable of regression tasks is automatically binned (argument \code{ task = mlr3::mlr_tasks$get("sonar") filter = FilterInformationGain$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterJMI.Rd b/man/FilterJMI.Rd index c625bdce..5ac25e82 100644 --- a/man/FilterJMI.Rd +++ b/man/FilterJMI.Rd @@ -5,7 +5,7 @@ \alias{FilterJMI} \alias{mlr_filters_jmi} \title{Joint Mutual Information Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterJMI } @@ -17,7 +17,7 @@ Calls \code{\link[praznik:JMI]{praznik::JMI()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterJMI$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -30,10 +30,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterJMIM.Rd b/man/FilterJMIM.Rd index 6f70058e..8e0b59db 100644 --- a/man/FilterJMIM.Rd +++ b/man/FilterJMIM.Rd @@ -5,7 +5,7 @@ \alias{FilterJMIM} \alias{mlr_filters_jmim} \title{Minimal Joint Mutual Information Maximisation Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterJMIM } @@ -17,7 +17,7 @@ Calls \code{\link[praznik:JMIM]{praznik::JMIM()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterJMIM$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterKruskalTest.Rd b/man/FilterKruskalTest.Rd index c6968449..041e3832 100644 --- a/man/FilterKruskalTest.Rd +++ b/man/FilterKruskalTest.Rd @@ -5,7 +5,7 @@ \alias{FilterKruskalTest} \alias{mlr_filters_kruskal_test} \title{Kruskal-Wallis Test Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterKruskalTest } @@ -17,7 +17,7 @@ Calls \code{\link[stats:kruskal.test]{stats::kruskal.test()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterKruskalTest$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterLinearCorrelation.Rd b/man/FilterLinearCorrelation.Rd index a0c0aa60..a0c7ed4c 100644 --- a/man/FilterLinearCorrelation.Rd +++ b/man/FilterLinearCorrelation.Rd @@ -5,7 +5,7 @@ \alias{FilterLinearCorrelation} \alias{mlr_filters_linear_correlation} \title{Linear Correlation Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterLinearCorrelation } @@ -17,7 +17,7 @@ Calls \code{\link[stats:cor]{stats::cor()}}. task = mlr3::mlr_tasks$get("mtcars") filter = FilterLinearCorrelation$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -28,10 +28,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterKruskalTest}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterMIM.Rd b/man/FilterMIM.Rd index 660998cb..025f4bb1 100644 --- a/man/FilterMIM.Rd +++ b/man/FilterMIM.Rd @@ -5,7 +5,7 @@ \alias{FilterMIM} \alias{mlr_filters_mim} \title{Conditional Mutual Information Based Feature Selection Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterMIM } @@ -17,7 +17,7 @@ Calls \code{\link[praznik:MIM]{praznik::MIM()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterMIM$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterLinearCorrelation}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterMRMR.Rd b/man/FilterMRMR.Rd index 5a46a787..089103e0 100644 --- a/man/FilterMRMR.Rd +++ b/man/FilterMRMR.Rd @@ -5,7 +5,7 @@ \alias{FilterMRMR} \alias{mlr_filters_MRMR} \title{Minimum redundancy maximal relevancy filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterMRMR } @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterLinearCorrelation}}, \code{\link{FilterMIM}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterNJMIM.Rd b/man/FilterNJMIM.Rd index 3308b3cb..7d9d0225 100644 --- a/man/FilterNJMIM.Rd +++ b/man/FilterNJMIM.Rd @@ -5,7 +5,7 @@ \alias{FilterNJMIM} \alias{mlr_filters_njmim} \title{Minimal Normalised Joint Mutual Information Maximisation Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterNJMIM } @@ -17,7 +17,7 @@ Calls \code{\link[praznik:NJMIM]{praznik::NJMIM()}}. task = mlr3::mlr_tasks$get("iris") filter = FilterNJMIM$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -29,10 +29,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterLinearCorrelation}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/FilterRankCorrelation.Rd b/man/FilterRankCorrelation.Rd index 03b49408..a241c9c1 100644 --- a/man/FilterRankCorrelation.Rd +++ b/man/FilterRankCorrelation.Rd @@ -5,7 +5,7 @@ \alias{FilterRankCorrelation} \alias{mlr_filters_rank_correlation} \title{Rank Correlation Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterRankCorrelation } @@ -17,7 +17,7 @@ Calls \code{\link[stats:cor]{stats::cor()}}. task = mlr3::mlr_tasks$get("mtcars") filter = FilterRankCorrelation$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -28,11 +28,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterKruskalTest}}, \code{\link{FilterLinearCorrelation}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, - \code{\link{FilterNJMIM}}, + \code{\link{FilterNJMIM}}, \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} + \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/Filter.Rd b/man/FilterResult.Rd similarity index 94% rename from man/Filter.Rd rename to man/FilterResult.Rd index e16a0e93..54fb750d 100644 --- a/man/Filter.Rd +++ b/man/FilterResult.Rd @@ -1,8 +1,8 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/Filter.R +% Please edit documentation in R/FilterResult.R \docType{data} -\name{Filter} -\alias{Filter} +\name{FilterResult} +\alias{FilterResult} \title{Filter Base Class} \format{\link[R6:R6Class]{R6::R6Class} object.} \description{ @@ -10,7 +10,7 @@ This is the base class for filters. Predefined filters are stored in \link{mlr_filters}. } \section{Construction}{ -\preformatted{f = Filter$new(id, task_type, param_set, param_vals, feature_types, packages) +\preformatted{f = FilterResult$new(id, task_type, param_set, param_vals, feature_types, packages) } \itemize{ \item \code{id} :: \code{character(1)}\cr @@ -84,7 +84,6 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} diff --git a/man/FilterSymmetricalUncertainty.Rd b/man/FilterSymmetricalUncertainty.Rd index a1ad1c0e..ec6e2c9d 100644 --- a/man/FilterSymmetricalUncertainty.Rd +++ b/man/FilterSymmetricalUncertainty.Rd @@ -5,7 +5,7 @@ \alias{FilterSymmetricalUncertainty} \alias{mlr_filters_symmetrical_uncertainty} \title{Symmetrical Uncertainty Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterSymmetricalUncertainty } @@ -18,7 +18,7 @@ The target variable of regression tasks is automatically binned (argument \code{ task = mlr3::mlr_tasks$get("sonar") filter = FilterSymmetricalUncertainty$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -31,8 +31,7 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, + \code{\link{FilterResult}}, \code{\link{FilterVariance}}, \code{\link{mlr_filters}} } \concept{Filter} diff --git a/man/FilterVariableImportance.Rd b/man/FilterVariableImportance.Rd index 5c4f0ce7..ca67919f 100644 --- a/man/FilterVariableImportance.Rd +++ b/man/FilterVariableImportance.Rd @@ -5,7 +5,7 @@ \alias{FilterVariableImportance} \alias{mlr_filters_variable_importance} \title{Variable Importance Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterVariableImportance } @@ -19,22 +19,7 @@ task = mlr3::mlr_tasks$get("iris") learner = mlr3::mlr_learners$get("classif.rpart") filter = FilterVariableImportance$new(learner = learner) filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } -\seealso{ -Other Filter: \code{\link{FilterAUC}}, - \code{\link{FilterCMIM}}, \code{\link{FilterDISR}}, - \code{\link{FilterGainRatio}}, - \code{\link{FilterInformationGain}}, - \code{\link{FilterJMIM}}, \code{\link{FilterJMI}}, - \code{\link{FilterKruskalTest}}, - \code{\link{FilterLinearCorrelation}}, - \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, - \code{\link{FilterNJMIM}}, - \code{\link{FilterRankCorrelation}}, - \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariance}}, \code{\link{Filter}}, - \code{\link{mlr_filters}} -} -\concept{Filter} +\concept{FilterResult} \keyword{datasets} diff --git a/man/FilterVariance.Rd b/man/FilterVariance.Rd index 6a579dcc..6ccd6cf3 100644 --- a/man/FilterVariance.Rd +++ b/man/FilterVariance.Rd @@ -5,7 +5,7 @@ \alias{FilterVariance} \alias{mlr_filters_variance} \title{Variance Filter} -\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{Filter}.} +\format{\link[R6:R6Class]{R6::R6Class} inheriting from \link{FilterResult}.} \usage{ FilterVariance } @@ -17,7 +17,7 @@ Calls \code{\link[stats:var]{stats::var()}}. Argument \code{na.rm} defaults to \ task = mlr3::mlr_tasks$get("mtcars") filter = FilterVariance$new() filter$calculate(task) -head(as.data.table(filter), 3) +as.data.table(filter)[1:3] } \seealso{ Other Filter: \code{\link{FilterAUC}}, @@ -30,9 +30,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{Filter}}, \code{\link{mlr_filters}} + \code{\link{mlr_filters}} } \concept{Filter} \keyword{datasets} diff --git a/man/mlr_filters.Rd b/man/mlr_filters.Rd index 23d3213f..3f0844aa 100644 --- a/man/mlr_filters.Rd +++ b/man/mlr_filters.Rd @@ -5,7 +5,7 @@ \title{Dictionary of Filters} \format{\link{R6Class} object} \description{ -A simple \link{Dictionary} storing objects of class \link{Filter}. +A simple \link{Dictionary} storing objects of class \link{FilterResult}. Each Filter has an associated help page, see \code{mlr_filters_[id]}. } \section{Usage}{ @@ -30,9 +30,9 @@ Other Filter: \code{\link{FilterAUC}}, \code{\link{FilterMIM}}, \code{\link{FilterMRMR}}, \code{\link{FilterNJMIM}}, \code{\link{FilterRankCorrelation}}, + \code{\link{FilterResult}}, \code{\link{FilterSymmetricalUncertainty}}, - \code{\link{FilterVariableImportance}}, - \code{\link{FilterVariance}}, \code{\link{Filter}} + \code{\link{FilterVariance}} } \concept{Dictionary} \concept{Filter} diff --git a/mlr3featsel.Rproj b/mlr3featsel.Rproj index 0ee12cde..2a7c1a91 100644 --- a/mlr3featsel.Rproj +++ b/mlr3featsel.Rproj @@ -19,4 +19,6 @@ BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source PackageCheckArgs: --as-cran -PackageRoxygenize: rd,collate,namespace +PackageRoxygenize: rd,namespace + +QuitChildProcessesOnExit: Yes diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 78ba4e76..ce630581 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -2,9 +2,9 @@ library(checkmate) library(mlr3) lapply(list.files(system.file("testthat", package = "mlr3"), pattern = "^helper.*\\.[rR]", full.names = TRUE), source) -expect_filter = function(f, task = NULL) { +expect_filter_result = function(f, task = NULL) { - expect_r6(f, "Filter", + expect_r6(f, "FilterResult", public = c("packages", "feature_types", "task_type", "param_set", "scores"), private = c(".calculate") ) @@ -16,15 +16,16 @@ expect_filter = function(f, task = NULL) { expect_function(private(f)$.calculate, args = "task") if (!is.null(f$scores)) { - expect_numeric(f$scores, any.missing = FALSE, names = "unique") - expect_false(is.unsorted(rev(f$scores))) + expect_data_table(f$scores) + checkSubset(colnames(f$scores), c("method", "scores")) } if (!is.null(task)) { x = f$clone(deep = TRUE)$calculate(task) - expect_class(x, "Filter") - expect_numeric(x$scores, any.missing = FALSE, names = "unique") - expect_names(names(x$scores), permutation.of = task$feature_names) - expect_false(is.unsorted(rev(x$scores))) + expect_class(x, "FilterResult") + # FIXME + # expect_data_table(f$scores) + # FIXME + # expect_names(names(x$scores), permutation.of = task$feature_names) } } diff --git a/tests/testthat/test_Filter.R b/tests/testthat/test_Filter.R index da96e581..e60b88a5 100644 --- a/tests/testthat/test_Filter.R +++ b/tests/testthat/test_Filter.R @@ -7,3 +7,23 @@ test_that("Errors for unsupported features", { filter = FilterLinearCorrelation$new() expect_error(filter$calculate(task)) }) + +test_that("fr$combine()", { + task = mlr3::mlr_tasks$get("iris") + + # create filters + fr1 = FilterMIM$new() + fr1$calculate(task) + fr2 = FilterVariance$new() + fr2$calculate(task) + + expect_data_table(fr1$scores, nrow = 4, ncol = 3) + expect_data_table(fr2$scores, nrow = 4, ncol = 3) + + fr2$combine(fr1) + + expect_data_table(fr2$scores, nrow = 8, ncol = 3) + + expect_filter_result(fr1) + expect_filter_result(fr2) +}) diff --git a/tests/testthat/test_FilterAUC.R b/tests/testthat/test_FilterAUC.R index b0263bea..b7734dc8 100644 --- a/tests/testthat/test_FilterAUC.R +++ b/tests/testthat/test_FilterAUC.R @@ -2,5 +2,5 @@ context("FilterAUC") test_that("FilterAUC", { f = FilterAUC$new() - expect_filter(f, task = mlr_tasks$get("sonar")) + expect_filter_result(f, task = mlr_tasks$get("sonar")) }) diff --git a/tests/testthat/test_FilterVariableImportance.R b/tests/testthat/test_FilterVariableImportance.R index 78379324..b144f65f 100644 --- a/tests/testthat/test_FilterVariableImportance.R +++ b/tests/testthat/test_FilterVariableImportance.R @@ -6,6 +6,6 @@ test_that("FilterVariableImportance", { f = FilterVariableImportance$new(learner = learner) f$calculate(task) fn = task$feature_names - expect_numeric(f$scores, len = length(fn), any.missing = FALSE, names = "unique") - expect_names(names(f$scores), permutation.of = fn) + expect_data_table(f$scores) + expect_names(f$scores$feature, permutation.of = fn) }) diff --git a/tests/testthat/test_mlr_filters.R b/tests/testthat/test_mlr_filters.R index 25b77ef1..50f19780 100644 --- a/tests/testthat/test_mlr_filters.R +++ b/tests/testthat/test_mlr_filters.R @@ -8,7 +8,7 @@ test_that("mlr_filters autotest", { f = mlr_filters$get(key) if (task$task_type %in% f$task_type) { f$calculate(task) - expect_filter(f, task = task) + expect_filter_result(f, task = task) } } @@ -17,7 +17,7 @@ test_that("mlr_filters autotest", { f = mlr_filters$get(key) if (task$task_type %in% f$task_type) { f$calculate(task) - expect_filter(f, task = task) + expect_filter_result(f, task = task) } } }) @@ -26,11 +26,11 @@ test_that("sanity check regression", { gen = mlr_generators$get("friedman1") task = gen$generate(500) - keys = as.data.table(mlr_filters)[map_lgl(task_type, is.element, el = "regr"), id] + keys = as.data.table(mlr_filters)[map_lgl(task_type, is.element, el = "regr"), key] keys = setdiff(keys, "variance") for (key in keys) { f = mlr_filters$get(key) f$calculate(task) - expect_true(startsWith(names(head(f$scores, 1L)), "important")) + expect_true(startsWith(f$scores$feature[1], "important")) } }) diff --git a/tic.R b/tic.R index 7b28586a..26a4261c 100644 --- a/tic.R +++ b/tic.R @@ -1,5 +1,5 @@ do_package_checks(error_on = "error") -if (ci_has_env("BUILD_PKGDOWN")) { - do_pkgdown(orphan = TRUE) +if (ci_on_travis()) { + do_pkgdown(orphan = TRUE, document = FALSE) }