cle*_*tus 61 algorithm charts graph
我需要一个相当聪明的算法来为图形(图表)提出"漂亮"的网格线.
例如,假设条形图的值为10,30,72和60.您知道:
最小值:10最大值:72范围:62
第一个问题是:你从什么开始?在这种情况下,0将是直观的值,但这不会阻碍其他数据集,所以我猜:
网格最小值应为0或低于范围内数据最小值的"nice"值.或者,可以指定.
网格最大值应该是该范围内最大值之上的"漂亮"值.或者,可以指定它(例如,如果显示百分比,则可能需要0到100,而不管实际值如何).
应该指定范围内的网格线(刻度线)的数量或给定范围内的数字(例如3-8),使得值"好"(即圆数)并且最大化图表区域的使用.在我们的例子中,80将是一个合理的最大值,因为它将使用90%的图表高度(72/80),而100将产生更多的浪费空间.
有人知道这个算法很好吗?语言是无关紧要的,因为我将按照我的需要实现它.
Mar*_*som 34
我用一种蛮力方法做到了这一点.首先,计算出可以放入空间的最大刻度标记数.将总值范围除以刻度数; 这是刻度线的最小间距.现在计算对数基数10的底数以得到刻度的大小,并除以该值.你应该得到1到10范围内的东西.只需选择大于或等于该值的圆数,然后乘以前面计算的对数.这是你的最终刻度线间距.
Python中的示例:
import math
def BestTick(largest, mostticks):
minimum = largest / mostticks
magnitude = 10 ** math.floor(math.log(minimum, 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
Run Code Online (Sandbox Code Playgroud)
编辑:您可以自由更改"好"间隔的选择.一位评论者似乎对所提供的选项不满意,因为实际的蜱数可能比最大数量少2.5倍.这是一个略微的修改,定义了一个很好的间隔的表.在这个例子中,我扩展了选择范围,使得刻度数不会小于最大值的3/5.
import bisect
def BestTick2(largest, mostticks):
minimum = largest / mostticks
magnitude = 10 ** math.floor(math.log(minimum, 10))
residual = minimum / magnitude
# this table must begin with 1 and end with 10
table = [1, 1.5, 2, 3, 5, 7, 10]
tick = table[bisect.bisect_right(table, residual)] if residual < 10 else 10
return tick * magnitude
Run Code Online (Sandbox Code Playgroud)
Ada*_*iss 29
这个问题有两个部分:
您可以使用对数处理第一部分:
range = max - min;
exponent = int(log(range)); // See comment below.
magnitude = pow(10, exponent);
Run Code Online (Sandbox Code Playgroud)
因此,例如,如果您的范围是50 - 1200,则指数为3,幅度为1000.
然后通过决定网格中需要多少个细分来处理第二部分:
value_per_division = magnitude / subdivisions;
Run Code Online (Sandbox Code Playgroud)
这是一个粗略的计算,因为指数已被截断为整数.您可能希望调整指数计算以更好地处理边界条件,例如通过舍入而不是采用int()
如果您最终得到太多细分.
Dre*_*kes 14
我使用以下算法.它与此处发布的其他内容类似,但它是C#中的第一个示例.
public static class AxisUtil
{
public static float CalcStepSize(float range, float targetSteps)
{
// calculate an initial guess at step size
var tempStep = range/targetSteps;
// get the magnitude of the step size
var mag = (float)Math.Floor(Math.Log10(tempStep));
var magPow = (float)Math.Pow(10, mag);
// calculate most significant digit of the new step size
var magMsd = (int)(tempStep/magPow + 0.5);
// promote the MSD to either 1, 2, or 5
if (magMsd > 5)
magMsd = 10;
else if (magMsd > 2)
magMsd = 5;
else if (magMsd > 1)
magMsd = 2;
return magMsd*magPow;
}
}
Run Code Online (Sandbox Code Playgroud)
CPAN 在这里提供了一个实现(参见源代码链接)
另请参见图轴的Tickmark算法
仅供参考,包含您的样本数据:
这是JavaScript中的另一个实现:
var calcStepSize = function(range, targetSteps)
{
// calculate an initial guess at step size
var tempStep = range / targetSteps;
// get the magnitude of the step size
var mag = Math.floor(Math.log(tempStep) / Math.LN10);
var magPow = Math.pow(10, mag);
// calculate most significant digit of the new step size
var magMsd = Math.round(tempStep / magPow + 0.5);
// promote the MSD to either 1, 2, or 5
if (magMsd > 5.0)
magMsd = 10.0;
else if (magMsd > 2.0)
magMsd = 5.0;
else if (magMsd > 1.0)
magMsd = 2.0;
return magMsd * magPow;
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
37335 次 |
最近记录: |