Home > Net >  How to create a function for optimum is better?
How to create a function for optimum is better?

Time:09-26

I want to create a function for "optimum is better" relationship as shown in the following figure enter image description here

I could able to create a function for "more is better" and "less is better" like

normalize <- function(x, na.rm=na.rm, relation=relation) {
  if (relation == "More is better") {
    normalize <- ((x - min(x, na.rm=na.rm))/
                    (max(x, na.rm=na.rm) - min(x, na.rm=na.rm)))
  } else {
    normalize <- 1 - ((x - min(x, na.rm=na.rm))/
                        (max(x, na.rm=na.rm) - min(x, na.rm=na.rm)))
  }
  return(normalize)
}

Here is a small data

set.seed(123)
value <- runif(50, min=3, max=8.5)

The "optimum is better" should take "more is better" up to a range or point (e.g. 6.5-7.5 for current data), in the optimum range the normalised value should be 1 and beyond the range or point it should be calculated as "less is better". How can I achieve this in R?

CodePudding user response:

Actually you could just transform the subsets.

FUN <- function(x, lower, upper, ...) {
  normalize <- function(x, ...) (x - min(x, ...))/(max(x, ...) - min(x, ...))
  x[x < lower] <- normalize(x[x < lower], ...)
  x[x > upper] <- 1 - normalize(x[x > upper], ...)
  x[x >= lower & x <= upper] <- 1 
  return(x)
}

lower <- 6.5; upper <- 7.5
value.star <- FUN(value, lower, upper, na.rm=TRUE)

plot(value, value.star, pch=20)
abline(v=c(lower, upper), lty=2)

enter image description here


Data

set.seed(123)
value <- runif(2.5e2, min=3, max=8.5)

CodePudding user response:

This function normalizes value in such a way that its output is always between 0 and 1. It returns exactly 1, iff the value is in the optimum range [a,b]. It returns a min max scaling iff value < a ("higher is better") and 1 - min-max-scaling it is larger than b ("lower is better")

library(tidyverse)

normalize <- function(value, a = 6.5, b = 7.5) {
  min_max_scaled <- (value - min(value)) / max(value)
  
  case_when(
    # before the range
    value < a ~ min_max_scaled,
    # within the range
    value >= a & value <= b ~ 1,
    # beyoned the range
    value > b ~ 1 - min_max_scaled
  )
}

  • Related