Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0691830
first commit - creation off PipeOp File
awinterstetter Aug 26, 2025
e091bcc
ideas for paste0 impelmented
awinterstetter Aug 27, 2025
2a9aa3e
reworking paste in PipeOpBasisSplines.(train-method does not work as …
awinterstetter Sep 2, 2025
63be015
BasisSplines PipeOp works in general (playing around with param df he…
awinterstetter Sep 3, 2025
7bd0676
hp implemented via init
awinterstetter Sep 3, 2025
aaa8950
PipeOpBasisSplines working version
awinterstetter Sep 5, 2025
c0acfe5
added PipeOpBasisSplines.R in DESCRIPTION-file
awinterstetter Sep 5, 2025
b862ea6
revised column-renaming of the result
awinterstetter Sep 5, 2025
250e4fe
updated DESCRIPTION; NAMESPACE
awinterstetter Sep 7, 2025
6f243fa
added tests for PipeOpBasisSplines
awinterstetter Sep 7, 2025
a4564ce
added test for po basissplines
awinterstetter Sep 12, 2025
3f34d0a
Renamed BasisSplines to Splines
awinterstetter Sep 16, 2025
c3847ba
fixed tests
awinterstetter Sep 18, 2025
7ef4a54
added packages in super$initialize and moved testing code to new file…
awinterstetter Sep 18, 2025
892e931
fixed column renaming of PipeOpBasisSplines
awinterstetter Sep 19, 2025
73b80a5
removed pop$state from examples
awinterstetter Sep 21, 2025
5065e7f
fixes in PipeOpSplines Tests
awinterstetter Sep 22, 2025
99c3254
added skip_if_not_installed in tests
awinterstetter Sep 22, 2025
26582ef
before restructuring it to a PipeOpTaskPreproc-object
awinterstetter Sep 26, 2025
2426c6d
changes before changing to PipeOpTaskPreproc
awinterstetter Sep 27, 2025
fce5dee
changed to PipeOpTaskPreproc
awinterstetter Sep 27, 2025
9927ea4
updated tests based on restructured PipeOp
awinterstetter Sep 27, 2025
ee010bd
post meeting with Martin; with notes; without changes in code
awinterstetter Oct 7, 2025
812e008
updated PipeOpSplines
awinterstetter Oct 8, 2025
874d68d
small updates for PipeOpSplines + associated tests
awinterstetter Oct 16, 2025
c2818af
small fix
awinterstetter Oct 16, 2025
8efca8d
changes in tags
awinterstetter Oct 27, 2025
ef8be48
updated doc and added Boundary.knots test
awinterstetter Oct 29, 2025
3e44006
added test for knots
awinterstetter Oct 30, 2025
622ab65
changes in doc
awinterstetter Nov 2, 2025
c8cd2cf
changes in doc
awinterstetter Nov 2, 2025
0000f52
doc changes (last commit before Positron transfer)
awinterstetter Nov 5, 2025
c6c4545
removed blank line
awinterstetter Nov 5, 2025
c51a222
next positron experiment
awinterstetter Nov 5, 2025
f6adcdf
doc and test fixes
awinterstetter Nov 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ Suggests:
future,
htmlwidgets,
ranger,
themis
themis,
splines
ByteCompile: true
Encoding: UTF-8
Config/testthat/edition: 3
Expand Down Expand Up @@ -188,6 +189,7 @@ Collate:
'PipeOpSmote.R'
'PipeOpSmoteNC.R'
'PipeOpSpatialSign.R'
'PipeOpSplines.R'
'PipeOpSubsample.R'
'PipeOpTextVectorizer.R'
'PipeOpThreshold.R'
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export(PipeOpSelect)
export(PipeOpSmote)
export(PipeOpSmoteNC)
export(PipeOpSpatialSign)
export(PipeOpSplines)
export(PipeOpSubsample)
export(PipeOpTargetInvert)
export(PipeOpTargetMutate)
Expand Down
139 changes: 139 additions & 0 deletions R/PipeOpSplines.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#' @title Transforms Numeric Features into Spline Basis Expansions
#'
#' @usage NULL
#' @name mlr_pipeops_splines
#' @format [`R6Class`][R6::R6Class] object inheriting from [`PipeOpTaskPreproc`]/[`PipeOp`].
#'
#' @description
#' Replaces numeric features with columns representing spline basis expansions.
#'
#' Depending on the type parameter, constructs polynomial B-splines [`splines::bs()`] or natural cubic splines [`splines::ns()`] for the respective column.
#'
#'
#' @section Construction:
#' ```
#' po("splines", param_vals = list())
#' ```
#'
#' * `id` :: `character(1)`\cr
#' Identifier of resulting object, default `"splines"`.
#' * `param_vals` :: named `list`\cr
#' List of hyperparameter settings, overwriting the hyperparameter settings that would otherwise be set during construction. Default `list()`.
#'
#' @section Input and Output Channels:
#' Input and output channels are inherited from [`PipeOpTaskPreproc`].
#'
#' The output is the input [`Task`][mlr3::Task] with the selected columns transformed according to the specified Splines Method.
#'
#' @section State:
#' The `$state` is a named `list` with the `$state` elements inherited from [`PipeOpTaskPreproc`].
#' After training the `Boundary.knots` will be given to the `$state`.
#'
#' @section Parameters:
#' The parameters are the parameters inherited from [`PipeOpTaskPreproc`], as well as:
#' * `type` :: `character(1)` \cr
#' `polynomial` when polynomial splines are applied [`splines::bs`] or
#' `natural` when natural splines are applied [`splines::ns`].
#' Default is `natural`.
#' * `df` :: `integer(1)` \cr
#' Number of degrees of freedom for calculation of splines basis matrix.
#' Default is `NULL`.
#' For further information look up [`splines::bs()`] or [`splines::ns()`].
#' * `knots` :: named `list` \cr
#' The internal breakpoints that define the spline. Parameter has to be passed as a named list.
#' Default is `NULL`. For further information consult [`splines::bs()`] or [`splines::ns()`].
#' * `intercept` :: `logical(1)` \cr
#' If `TRUE`, an intercept is included in the basis. Default is `FALSE`.
#' For further information look up [`splines::bs()`] or [`splines::ns()`].
#' * `degree` :: `integer(1)` \cr
#' This parameter depends on type = "polynomial". Degree of the polynomial used to compute B-splines.
#' Default is `3`. For further information look up [`splines::bs()`].
#' * `Boundary.knots` :: named `list` \cr
#' Boundary points at which to anchor the spline basis. Parameter has to be passed as a named list.
#' Default is `NULL`.
#' For further information look up [`splines::bs()`] or [`splines::ns()`].
#'
#' @section Internals:
#' Creates spline basis via [`splines::bs`]/[`splines::ns`] function depending on `type`.
#' After training, the `Boundary.knots` that are either defined in the Parameter Set
#' or have been calculated during training will be passed to the `$state` of the PipeOp.
#'
#' @section Fields:
#' Only fields inherited from [`PipeOp`].
#'
#' @section Methods:
#' Only methods inherited from [`PipeOpTaskPreproc`]/[`PipeOp`].
#'
#' @examples
#' library("mlr3")
#'
#' task = tsk("iris")
#' pop = po("splines")
#'
#' pop$train(list(task))[[1]]$data()
#'
#' pobk = po("splines", param_vals = list(Boundary.knots = list("Petal.Length" = c(0, 4), "Petal.Width" = c(4, 7), "Sepal.Length" = c(1, 5), "Sepal.Width" = c(3, 6))))
#' pobk$train(list(task))[[1]]$data()
#'
#' @family PipeOps
#' @template seealso_pipeopslist
#' @include PipeOpTaskPreproc.R
#' @export

PipeOpSplines = R6Class("PipeOpSplines",
inherit = PipeOpTaskPreproc,
public = list(
initialize = function(id = "splines", param_vals = list()) {
ps = ps(
type = p_fct(levels = c("polynomial", "natural"), init = "natural", tags = c("train", "splines", "required")),
df = p_int(lower = 1, upper = Inf, special_vals = list(NULL), init = NULL, tags = c("train", "splines")),
knots = p_uty(special_vals = list(NULL), init = NULL, tags = c("train", "splines")),
degree = p_int(lower = 1, upper = Inf, default = 3, depends = type == "polynomial", tags = c("train", "splines")),
intercept = p_lgl(init = FALSE, tags = c("train", "splines")),
Boundary.knots = p_uty(tags = c("train", "splines"))
)
super$initialize(id = id, param_set = ps, param_vals = param_vals, packages = c("splines", "stats"))
}
),
private = list(
.train_dt = function(dt, levels, target) {
result = list()
bk = list()
pv = self$param_set$get_values(tags = "splines")
for (i in colnames(dt)) {
args = pv
args$type = NULL
args$knots = pv$knots[[i]]
args$Boundary.knots = pv$Boundary.knots[[i]]
if (pv$type == "polynomial") {
result[[i]] = invoke(splines::bs, .args = args, x = dt[[i]], warn.outside = FALSE)
} else {
result[[i]] = invoke(splines::ns, .args = args, x = dt[[i]])
}
colnames(result[[i]]) = paste0("splines.", seq_len(ncol(result[[i]])))
bk[[i]] = attributes(result[[i]])$Boundary.knots
}
self$state$Boundary.knots = bk
result
},
.predict_dt = function(dt, levels) {
result = list()
pv = self$param_set$get_values(tags = "splines")
for (i in colnames(dt)) {
args = pv
args$type = NULL
args$knots = pv$knots[[i]]
args$Boundary.knots = self$state$Boundary.knots[[i]]
if (pv$type == "polynomial") {
result[[i]] = invoke(splines::bs, .args = args, x = dt[[i]], warn.outside = FALSE)
} else {
result[[i]] = invoke(splines::ns, .args = args, x = dt[[i]])
}
colnames(result[[i]]) = paste0("splines.", seq_len(ncol(result[[i]])))
}
result
}
)
)

mlr_pipeops$add("splines", PipeOpSplines)
83 changes: 83 additions & 0 deletions attic/PipeOpSPlines - testing code.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

# po = po("splines", df = 1)
# po_result = po$train(list(tsk("iris")))[[1]]$data()

# po = po("splines", type = "polynomial", df = 2, degree = 4)
# po_result = po$train(list(tsk("iris")))[[1]]$data()
# po_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length) + splines::bs(Sepal.Width) + splines::bs(Petal.Length) + splines::bs(Petal.Width), data = iris)

# selecting columns
# sel_cyl = selector_grep("Sepal.Length")
# pos = po("basissplines", affect_columns = sel_cyl)
# pos_result = pos$train(list(tsk("iris")))[[1]]$data()
# pos_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length), data = iris)


# podf3 = po("basissplines", df = 3)
# podf3_result = podf3$train(list(tsk("iris")))[[1]]$data()
# podf3_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length, df = 3) + splines::bs(Sepal.Width, df = 3) + splines::bs(Petal.Length, df = 3) + splines::bs(Petal.Width, df = 3), data = iris)

# podf4 = po("basissplines", df = 4)
# podf4_result = podf4$train(list(tsk("iris")))[[1]]$data()
# podf4_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length, df = 4) + splines::bs(Sepal.Width, df = 4) + splines::bs(Petal.Length, df = 4) + splines::bs(Petal.Width, df = 4), data = iris)

# podf7 = po("basissplines", df = 7)
# podf7_result = podf7$train(list(tsk("iris")))[[1]]$data()
# podf7_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length, df = 7) + splines::bs(Sepal.Width, df = 7) + splines::bs(Petal.Length, df = 7) + splines::bs(Petal.Width, df = 7), data = iris)

# podeg3df2 = po("basissplines", degree = 3, df = 2)
# podeg3df2_result = podeg3df2$train(list(tsk("iris")))[[1]]$data()
# podeg3df2_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length, degree = 3, df = 2) + splines::bs(Sepal.Width, degree = 3, df = 2) + splines::bs(Petal.Length, degree = 3, df = 2) + splines::bs(Petal.Width, degree = 3, df = 2), data = iris)


# podeg5df8 = po("basissplines", degree = 5, df = 8)
# podeg5df8_result = podeg5df8$train(list(tsk("iris")))[[1]]$data()
# podeg5df8_result_calc = stats::model.matrix(Species ~ splines::bs(Sepal.Length, degree = 5, df = 8) + splines::bs(Sepal.Width, degree = 5, df = 8) + splines::bs(Petal.Length, degree = 5, df = 8) + splines::bs(Petal.Width, degree = 5, df = 8), data = iris)

# pons = po("basissplines", factor = "natural")
# pons_result = pons$train(list(tsk("iris")))[[1]]$data()
# pons_result_calc = stats::model.matrix(Species ~ splines::ns(Sepal.Length) + splines::ns(Sepal.Width) + splines::ns(Petal.Length) + splines::ns(Petal.Width), data = iris)

# pons_error = po("basissplines", factor = "natural", df = 3, degree = 4)

# ponsdf5 = po("basissplines", factor = "natural", df = 5)
# ponsdf5_result = ponsdf5$train(list(tsk("iris")))[[1]]$data()
# ponsdf5_result_calc = stats::model.matrix(Species ~ splines::ns(Sepal.Length, df = 5) + splines::ns(Sepal.Width, df = 5) + splines::ns(Petal.Length, df = 5) + splines::ns(Petal.Width, df = 5), data = iris)




# pop = po("basissplines", df = 5)
# pop$train(list(tsk("mtcars")))[[1]]$data()

# poc = po("basissplines", df = 4, factor = "natural")
# poc$train(list(tsk("mtcars")))[[1]]$data()

# df als hyperparameterf
# das ziel ist es dass wir diese model.matrix für alle features kriegen
# original features behalten dann feature_union ==> egaluser verantwortung


#splines.cyl.1

# task = tsk("mtcars")

# list(task)[[1]]$data()
# pop = po("modelmatrix", formula = ~ splines::ns(task$data()$cyl, 2) + splines::ns(task$data()$hp, 2) +
# splines::ns(task$data()$disp, 2) + splines::ns(task$data()$drat, 2) + splines::ns(task$data()$wt, 2) +
# splines::ns(task$data()$qsec, 2) + splines::ns(task$data()$vs, 2) + splines::ns(task$data()$am, 2) +
# splines::ns(task$data()$gear, 2) + splines::ns(task$data()$carb, 2))
# pop$train(list(task))[[1]]$data()

# pob = po("modelmatrix", formula = ~ splines::bs(task$data()$cyl, 2) + splines::bs(task$data()$hp, 2) +
# splines::bs(task$data()$disp, 2) + splines::bs(task$data()$drat, 2) + splines::bs(task$data()$wt, 2) +
# splines::bs(task$data()$qsec, 2) + splines::bs(task$data()$vs, 2) + splines::bs(task$data()$am, 2) +
# splines::bs(task$data()$gear, 2) + splines::bs(task$data()$carb, 2))

# pob$train(list(task))[[1]]$data()


# fit <- lm(mpg ~ splines::ns(cyl, df = 2) + splines::ns(hp, df = 2), data = mtcars)
# model.matrix(fit) # this is what we want to get as a result from PipeOpSplineBasis

# as.data.frame(stats::model.matrix(mpg ~ splines::ns(cyl, 2) + splines::ns(task$data()$hp, 2), data = mtcars))
1 change: 1 addition & 0 deletions man/PipeOp.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/PipeOpEncodePL.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/PipeOpEnsemble.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/PipeOpImpute.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/PipeOpTargetTrafo.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/PipeOpTaskPreproc.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/PipeOpTaskPreprocSimple.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_adas.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_blsmote.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_boxcox.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_branch.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_chunk.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_classbalancing.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_classifavg.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_classweights.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_colapply.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/mlr_pipeops_collapsefactors.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading