Open liuyanguu opened 1 month ago
If you're trying to flip the directions of indicators, you probably want to use the Normalise()
function, which does that automatically for you based on the directions specified in iMeta
. It also lets you pass custom functions to it. You can also do a completely custom operation using the Custom()
function if you can't do it another way.
Many thanks for your prompt reply. I have tried Normalise and encounter the same issue. Unfortunately setting global = FALSE is not enough for custom function
library("COINr")
n_f_custom <- function(x, direction) {
if (direction == -1) {
return(1 - x)
} else {
return(x) # Identity transformation if direction is 1
}
}
purse <- build_example_purse(up_to = "new_coin")
purse <- Normalise(purse, dset = "Raw", global_specs = list(f_n = "f_custom", f_n_para = "use_iMeta"), global = FALSE)
reports "Error in get_iMeta_norm_paras(coin, func_name = global_specs[["f_n"]]) : Your normalisation function 'f_custom' does not have support for iMeta parameters."
I have also tried Custom
, but it seems it cannot use iMeta.
purse <- build_example_purse(up_to = "new_coin")
purse <- Custom(purse, dset = "Raw", f_cust = f_custom, f_cust_para = "use_iMeta")
Update: I managed to get
purse <- Normalise(purse, dset = "Raw", global_specs = list(f_n = "f_custom", f_n_para = "use_iMeta"), global = FALSE)
work by modifying the get_iMeta_norm_paras
function, adding the following lines:
required_cols <- switch(
func_name,
n_f_custom = c("Direction"),
...)
# add `drop = FALSE` since I only have one argument
paras <- iMeta[iMeta$iCode == names(l_n)[ii], required_cols, drop = FALSE] # drop = FALSE to keep as data frame
# add to list component
l$f_n_para <- switch(
func_name,
n_f_custom = list(direction = paras$Direction),
...)
@liuyanguu have you looked at the documentation on normalisation at https://bluefoxr.github.io/COINr/articles/normalise.html#coins
As far as I can tell you just want to flip the indicator directions, and this is taken care of by Normalise() without needing to pass your function to it. Normally the reversal of directions is done at the normalisation step, in addition to another scaling operation such as min-max. All of this is built into the package. Also please check the function documentation - if a function doesn't explicitly say it can access iMeta then it can't, these are special cases, again it is written out in the documentation.
Dear @bluefoxr, I have read all the documentation. Indeed, what I am doing is very simple, but I am not only flipping the indicator direction — I am keeping the same value if it is a positive indicator and calculating (1 - x) if it is a negative indicator. And I'd like to use f_n_para = use_iMeta
. I see no other way to get Normalise
work with a custom function (which pulls information from iMeta) without modifying the get_iMeta_norm_paras
function.
purse <- Normalise(purse, dset = "Raw", global_specs = list(f_n = "f_custom", f_n_para = "use_iMeta"), global = FALSE)
I think then maybe the answer is a Custom operation, passing the iMeta data frame "manually" (or just the direction and iCode columns) to the f_cust_para
argument.
In Custom.purse() the operation happens like this:
# run global dset through function
iDatas_c <- do.call(f_cust, c(list(x = iDatas), f_cust_para))
So if you make a function like your one above, where it looks up the direction for each column, it should do the trick.
I'm sorry for the multiple questions. I have a quick question: all my indicators are percentages and I want to apply a simple function like below to all indicators, is it possible to use the "Treat" function for it?
basically return the same value if direction is 1 and (1 - x) if the direction is -1.
I tried
but nothing changes and all values remain the same? Sorry I haven't figured out the right way to do it...
Thank you so much for your help. Much appreciated!