饼图百分比 bug

上周给 ECharts 修了一个挺有意思的 bug——饼图百分比由于四舍五入总和不为 100%。

举一个简单的例子你就懵逼明白了:

假设饼图由三部分组成,占比分别为:20.3%、30.4%、49.3%,总和是 100%。但是如果用四舍五入的方法保留整数部分的话,分别为:20%、30%、49%,这样总和就只有 99% 了。

想一下,这个问题应该如何解决呢?

我们希望把剩余的 1% 分配给哪部分呢?

作为一个没有什么额外信息的饼图而言,我们应该很乐意把这多余的 1% 分配给 30.4% 的部分,毕竟它的小数部分比另外两个部分大 0.1%。因而相应地,修复这个 bug 的算法思路是这样的(我用比较通俗而不精确的方法介绍,更精确的说法详见 Wiki):

  1. 首先,根据保留小数位数的精度,先向下取整分配没有争议的百分比(在上面的例子中,先分配整数部分,分别分配 20%、30%、49%);
  2. 计算剩余可分配的百分比(在上面的例子中,100% - 20% - 30% - 49% 得到 1%);
  3. 确定剩余百分比可以分配成几份(在上面的例子中,由于我们想精确到整数部分,因此 1% 只能分成一份);
  4. 将每个部分的总百分比减去已经分配的百分比,并从高到低排序(在上面的例子中,分别是 0.3%、0.4%、0.3%,排序后第二个部分最高);
  5. 将剩余份数根据上面排序后的顺序,依次分配,每次一份,直到分完(在上面的例子中,给第二部分分配一份 1% 后就没有剩余的份数了);

至此,这个 bug 就修完了。

那么,这和议会席位又有什么关系呢?

议会席位分配

其实一开始看到这个 issue 的时候,我就想起了前阵子在读的《数据之巅》里面提到的——在美国初创期,分配议会席位的时候,根据各州人口比例决定议会席位。和饼图保留百分比的 bug 类似,由于席位只能精确到整数部分,这就不可避免地会有小数点上的争议。

而议会的问题则比饼图复杂得多。而根本原因在于,一个席位之差对于一个州也是非常重要的。

上文我之所以用“作为一个没有什么额外信息的饼图而言”这样的表述,就在于像“把多余的席位分配给小数点部分大的州”这样的做法未必是最合理的。让我们看看《数据之巅》是怎么说的——

那么,在这种情况下,怎样分配才最合理呢?

其实,就像我们对“公平”的定义很多时候也偏向了对自己有利的一面,不管我们有没有意识到。所以,各个州也不能免俗地认为那些对自己有利的算法更为合理公平。这本书还介绍了一些其他的算法,有兴趣的推荐看一下。

其中……

因为追求数学最佳,杰斐逊的方法在数学上更为复杂,很多国会议员因为听不明白而兴起全无。

——《数据之巅》

听不明白,哈哈哈哈,不由笑出声……