【发布时间】:2010-10-11 08:16:26
【问题描述】:
我需要制作一个具有优化 y 轴最大值的图表。
我目前制作图表的方法只是使用所有图表的最大值,然后将其除以 10,并将其用作网格线。不是我写的。
更新说明:这些图表已更改。一旦我修复了代码,我的动态图就开始工作了,这让这个问题变得荒谬(因为示例中不再有任何错误)。我已经用静态图像更新了这些,但有些答案引用了不同的值。记住这一点。 到目前为止,2 月份有 12003 到 14003 个呼入电话。内容丰富,但丑陋。
我想避免使用 y 轴编号的看起来像猴子的图表。
使用 Google 图表 API 会有所帮助,但这仍然不是我想要的。 数字很干净,但 y 值的顶部始终与图表上的最大值相同。此图表的范围从 0 到 1357。我需要计算出 1400 的正确值,有问题。
我在这里加入rbobby 对“好”数字的定义,因为它解释得很好。
- “好”数字是指具有 3 个或更少非零数字的数字(例如 1230000)
- 一个“好”的数字与零数字具有相同或少数几个非零数字(例如,1230 不好,1200 好)
- 最好的数字是 3 个零的倍数(例如“1,000”、“1,000,000”)
- 第二好的数字是由 3 个零和 2 个零组成的整数(例如“1,500,000”、“1,200”)
解决方案
我找到了使用 Mark Ransom 想法的修改版本来获得我想要的结果的方法。
拳头,Mark Ransom 的代码在给定刻度数时确定刻度之间的最佳间距。有时,这个数字最终会是图表上最高值的两倍多,具体取决于您想要多少条网格线。
我正在运行带有 5、6、7、8、9 和 10 条网格线(刻度线)的 Mark 代码,以找出其中最低的一条。值为 23 时,图表的高度变为 25,网格线位于 5、10、15、20 和 25 处。值为 26 时,图表的高度为 30,网格线位于 5、10 , 15, 20, 25, 30。网格线之间的间距相同,但数量更多。
以下是复制 Excel 所做的以使图表变得精美的步骤。
- 暂时将图表的最高值提高约 5%(这样图表的最高点和图表区域的顶部之间总是有一些空间。我们希望 99.9 向上舍入到 120)
- 找到最佳网格线位置 适用于 5、6、7、8、9 和 10 格 行。
- 从这些数字中选出最小的。请记住获得该值所需的网格线数。
- 现在您有了最佳图表高度。线/条永远不会与图表顶部对接,并且您拥有最佳的刻度数。
PHP:
function roundUp($maxValue){
$optiMax = $maxValue * 2;
for ($i = 5; $i <= 10; $i++){
$tmpMaxValue = bestTick($maxValue,$i);
if (($optiMax > $tmpMaxValue) and ($tmpMaxValue > ($maxValue + $maxValue * 0.05))){
$optiMax = $tmpMaxValue;
$optiTicks = $i;
}
}
return $optiMax;
}
function bestTick($maxValue, $mostTicks){
$minimum = $maxValue / $mostTicks;
$magnitude = pow(10,floor(log($minimum) / log(10)));
$residual = $minimum / $magnitude;
if ($residual > 5){
$tick = 10 * $magnitude;
} elseif ($residual > 2) {
$tick = 5 * $magnitude;
} elseif ($residual > 1){
$tick = 2 * $magnitude;
} else {
$tick = $magnitude;
}
return ($tick * $mostTicks);
}
Python:
import math
def BestTick(largest, mostticks):
minimum = largest / mostticks
magnitude = 10 ** math.floor(math.log(minimum) / math.log(10))
residual = minimum / magnitude
if residual > 5:
tick = 10 * magnitude
elif residual > 2:
tick = 5 * magnitude
elif residual > 1:
tick = 2 * magnitude
else:
tick = magnitude
return tick
value = int(input(""))
optMax = value * 2
for i in range(5,11):
maxValue = BestTick(value,i) * i
print maxValue
if (optMax > maxValue) and (maxValue > value + (value*.05)):
optMax = maxValue
optTicks = i
print "\nTest Value: " + str(value + (value * .05)) + "\n\nChart Height: " + str(optMax) + " Ticks: " + str(optTicks)
【问题讨论】:
-
这是一个绝妙的问题。写得好,布局好,显然经过研究,甚至包括插图。为什么没有其他人支持它?
-
不适用于大数字,间隔变大
-
@Matjaž Jurečič 看看这个stackoverflow.com/a/35254002/2277240 是否适合你。
-
@FGRibreau 听起来工作量很大。我只是要用静态副本替换它。