bluefoxr / COINr

COINr
https://bluefoxr.github.io/COINr/
Other
22 stars 7 forks source link

weightOpt error #5

Closed komalsrathi closed 1 year ago

komalsrathi commented 2 years ago

Hi,

I am trying to run the weightOpt function as follows but not sure what the error is and how to resolve:

Here is my dataframe for reproducibility:

dat_sub <- structure(list(UnitCode = c("PDGFRA_1", "PDGFRA_2", "RPL22_3", "ENO1_4", "MACF1_5", "YBX1_6"), 
                          UnitName = c("PDGFRA", "PDGFRA", "RPL22", "ENO1", "MACF1", "YBX1"), 
                          Tier1_variant = c(0, 1, 0, 0, 0, 0), 
                          Tier2_variant = c(1, 0, 0, 0, 0, 0), 
                          Tier3_variant = c(0, 0, 0, 0, 0, 0)), 
                     row.names = c(NA, 6L), class = "data.frame")

# Create metadata table for COIN object, assigning weights
output_meta <- data.frame('IndName' = colnames(dat_sub)[3:ncol(dat_sub)], 
                          'IndCode' = colnames(dat_sub)[3:ncol(dat_sub)],
                          'Direction' = c(rep(1, 3)),
                          'IndWeight' = c(3, 2, 1),
                          'Agg1' = rep("rank", 3))

# Create aggregation metadata table for COIN object
agg_metadata <- data.frame('AgLevel' = c(2),
                           'Code' = c('rank'),
                           'Name' = c('Rank'),
                           'Weight' = c(1))

# Assemble COIN object with data and metadata, normalise, aggregate, and get results
ASEM <- COINr::assemble(IndData = dat_sub, IndMeta = output_meta, AggMeta = agg_metadata)
ASEM <- COINr::normalise(ASEM, ntype = "rank", dset = 'Raw')
ASEM <- COINr::aggregate(ASEM, agtype = "geom_mean", dset = "Normalised")

# getResults works fine
COINr::getResults(ASEM, tab_type = "Summ") 

  UnitCode UnitName rank Rank
1 PDGFRA_2   PDGFRA 4.35    1
2 PDGFRA_1   PDGFRA 3.88    2
3  RPL22_3    RPL22 3.08    3
4   ENO1_4     ENO1 3.08    3
5  MACF1_5    MACF1 3.08    3
6   YBX1_6     YBX1 3.08    3

# weightOpt does not work for some reason
COINr::weightOpt(COIN = ASEM, 
          itarg = c(3, 2, 1), 
          aglev = 1, 
          out2 = "COIN", 
          cortype = 'spearman')

Error in COIN$Parameters$AggCodes[[length(COIN$Parameters$AggCodes) - : 
attempt to select less than one element in get1index <real>
bluefoxr commented 2 years ago

Hi, I can't reproduce your error, the first few lines of your example don't run. Can you make sure the example runs without anything in your environment please?

p.s. from your error it might be because you are using tibbles. Try also converting everything to data frames. If you send me a reproducible example I'll try to fix this

komalsrathi commented 2 years ago

Hi - please see above, I have updated my code in the ticket itself. It has been tested on a fresh R environment so it should run for you as well. I am getting the same errors as before after using data.frame instead of tibble

bluefoxr commented 1 year ago

Hi @komalsrathi I have had a look at the problem. There are a few things to mention here.

First of all, you should know that COINr has just undergone a very major update which has changed a lot of the syntax. The weight optimisation function has been largely re-written, among many other things. You can install the new version of COINr v1.0.0 from this repo or via CRAN. Probably the issue you describe here would not happen in the new version.

I am maintaining the older version of COINr (v0.6.1), which you are probably using, now as a separate package called "COINr6". See https://github.com/bluefoxr/COINr6

If you want to run your existing code, you would now have to install COINr6 from github (see the readme there to see how) and now load COINr6 instead of COINr.

And/or, you can just install the new COINr version and work from there.

Now, about your issue, it was a bug, and this is now fixed in COINr6. However, there is another issue. Because one of your indicators has all the same values, the correlation between that and the highest aggregation level is NA. Therefore it is impossible to optimise the weights based on correlations. I have now added a line to catch this eventuality.

I think therefore you need to reformulate your problem. Plus I would advise to move to COINr v1.0.0 (sorry for the upheaval) unless you prefer to go for COINr6.

Hope that all makes sense!

# install COINr6 to run this
devtools::install_github("bluefoxr/COINr6")

dat_sub <- structure(list(UnitCode = c("PDGFRA_1", "PDGFRA_2", "RPL22_3", "ENO1_4", "MACF1_5", "YBX1_6"),
                          UnitName = c("PDGFRA", "PDGFRA", "RPL22", "ENO1", "MACF1", "YBX1"),
                          Tier1_variant = c(0, 1, 0, 0, 0, 0),
                          Tier2_variant = c(1, 0, 0, 0, 0, 0),
                          Tier3_variant = c(0, 0, 0, 0, 0, 0)),
                     row.names = c(NA, 6L), class = "data.frame")

# Create metadata table for COIN object, assigning weights
output_meta <- data.frame('IndName' = colnames(dat_sub)[3:ncol(dat_sub)],
                          'IndCode' = colnames(dat_sub)[3:ncol(dat_sub)],
                          'Direction' = c(rep(1, 3)),
                          'IndWeight' = c(3, 2, 1),
                          'Agg1' = rep("rank", 3))

# Create aggregation metadata table for COIN object
agg_metadata <- data.frame('AgLevel' = c(2),
                           'Code' = c('rank'),
                           'Name' = c('Rank'),
                           'Weight' = c(1))

# Assemble COIN object with data and metadata, normalise, aggregate, and get results
ASEM <- COINr6::assemble(IndData = dat_sub, IndMeta = output_meta, AggMeta = agg_metadata)
ASEM <- COINr6::normalise(ASEM, ntype = "rank", dset = 'Raw')
ASEM <- COINr6::aggregate(ASEM, agtype = "geom_mean", dset = "Normalised")

# getResults works fine
COINr6::getResults(ASEM, tab_type = "Summ")

# weightOpt still doesn't work, but because of the problem formulation now. Bug corrected.
test1 <- COINr6::weightOpt(COIN = ASEM,
                 itarg = c(3, 2, 1),
                 aglev = 1,
                 out2 = "COIN",
                 cortype = 'spearman')
komalsrathi commented 1 year ago

Thanks @bluefoxr.

I just installed the latest version of COINr but looks like the old code will not work for it. For e.g. I tried to replace this line ASEM <- COINr::assemble(IndData = dat_sub, IndMeta = output_meta, AggMeta = agg_metadata) with ASEM <- COINr::new_coin(iData = dat_sub, iMeta = output_meta) but does not seem to work. The aggregation metadata is also not required anymore. Looks like a lot of the other function names as well as input parameters have been changed as well. Is there a README that shows the corresponding code with the new version?

bluefoxr commented 1 year ago

Hi yes, I'm afraid the new COINr version is a very heavy one off modification to the package. You can read about it here: https://bluefoxr.github.io/COINr/articles/v1.html . Also each old-syntax function should redirect you to the new-syntax equivalent (with a few exceptions).

As mentioned, either you can continue using the old syntax by installing COINr6, or else you have to adapt to the new syntax. Building a new coin now only requires two data frames. I think especially in your case, which is fairly few indicators and units, it shouldn't take long to convert. You might want to check out the COIN_to_coin() function as well.

bluefoxr commented 1 year ago

I will close the issue now because the bug is fixed in COINr6 and AFAIK in COINr v1.0.0