Error "The weights don't sum to 1" occurs, but they do sum to 1 (MCDM package for R)

553 Views Asked by At

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?

1

There are 1 best solutions below

2
On

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.