0

I'm running a sensitivity analysis for a multi-criteria decision model. The model is run in R, using the package MCDM. A key component of the model is that it relies on a user-given set of weights that must sum to 1. I am working with weight preferences that originally did not sum to 1 but which I normalized to sum to 1.

weights <- data.frame("w1"=0.03125, "w2"=0.53125, "w3"=0.84375, "w4"=0.21875, "w5"=0.46875, "w6"=0.28125, "w7"=0.96875)

normal_weights <- weights/rowSums(weights)

When I check to confirm that the new weights sum to 1, R confirms they do...

rowSums(normal_weights)

...returns a "1".

However, when I then run the model, I then get the package-specific error that the weights do not sum to 1.

Based on trying to troubleshoot this problem myself, I'm guessing it has something to do with:

  1. The weights are stored as doubles
  2. Usually this is fine as 16ish digits past the decimal place is more than needed...but not always
  3. rowSums doesn't actually return true "1" so if there's a slight precision issue with one set of weights, I don't notice it until I run the model
  4. The error occurs

Is this what is probably going on? And if so, how do I fix it? Is there a way to maintain precision? A better way to normalize that won't cause this issue?

Edit: I understand that the R Q&A "Why are these numbers not equal?" answers why R does this; but, that post does not answer my question of what are some workarounds to deal with this issue, considering I cannot change package I'm working with?

MSS
  • 3,306
  • 1
  • 19
  • 50
Savi
  • 49
  • 7
  • Learn about floating point arithmetic in software. Floating point data types can only represent some values. In most languages reading a literal returns the native type value that is closest to its input & each arithmetic operator returns the native type value that is closest to its ideal result applied to its (native type) inputs. Then you have to decide what the actual specification of your program is in terms of suitable notions of precision & accuracy. Then you have to write an appropriate program. Ask a question when you get stuck after you understand more about the issues. PS [mre] – philipxy Jul 03 '19 at 04:22
  • Still no [mre]--cut & paste & runnable code; example input with desired & actual output (including verbatim error messages); tags & clear specification & explanation. That includes the least code you can give that is code that you show is OK extended by code that you show is not OK. (Debugging fundamental.) PS Please act on my last comment. Eg: You say the API "relies on a user-given set of weights that must sum to 1". What exactly does the documentation say? What exactly is your code, input & output? With your new FP knowledge what reasoning have you now additionally tried? [ask] – philipxy Jul 03 '19 at 20:00

1 Answers1

3

this is quite normal, it is very difficult to check whether a number is 1. just because R prints 1 it does not mean it is exactly one. in fact you can easily see that

identical(rowSums(normal_weights),1)
[1] FALSE

and in fact you can see that

 rowSums(normal_weights) -1
[1] -1.110223e-16

so I would do two things:

1) establish that the weights sum up to 1 with a reasonable accuracy, something like 1e-8 (this really depends on your problem)

2) to get around the error just define the last element of normal_weights as 1 - the sum of the other ones:

 normal_weights[length(normal_weights)] <- 1- 
 sum(normal_weights[1:(length(normal_weights)-1)])

 identical(rowSums(normal_weights),1)
 [1] TRUE

I guess the MCMC function you are using as an x == y statement somewhere, it would have probably been better if they had a tolerance test, but that is another story.

FGirosi
  • 106
  • 5
  • Thank you. I think this might be it, but I don't quite understand how to implement Step 2. I tried both your code and normal_weights[1,7] <- 1-sum(normal_weights[1:(length(normal_weights)-1)]) and both versions result in the 'identical' test still returning FALSE. – Savi Jul 03 '19 at 05:45
  • sorry this does not work for you. it may depend on the machine we are using, that we get different results? this goes beyond my knowledge of R I am afraid. can you use fewer digits and round a bit? it may improve your chances. do you know in which function of MCMC the error occur? maybe you cold download the source code and modify the offending statement. but I agree with you that the posted link does not solve your problem, given that you cannot change the function you are using. you may need to post a whole reproducible example and hope someone more knowledgeable picks it up. – FGirosi Jul 03 '19 at 21:24