题
我在寻找一个"不错的数字"算法确定的标签,在一个日期/时间价值的轴。我很熟悉 保罗Heckbert是很好的号码算法.
我有一个阴谋,显示的日期/时间在X轴上的和用户能够放大看看一个小时间框架。我在寻找一种算法,挑选很好的日期显示在蜱。
例如:
- 看一天这样:1/1 12:00, 1/1 4:00, 1/1 8:00...
- 寻找一个周:1/1,1/2,1/3的...
- 看一个月:1/09,2/09,3/09...
好的标签蜱不需要对应于第一点可见的,但是接近它。
是任何人都熟悉这样的算法?
解决方案
的'不错的数字文章链接,以提到的是
最好的数字,在小数是1,2,5,所有电力的10倍,这些数字
所以我想做的事情相似的日期/时间你需要开始通过类似的破坏的组件。因此,采取不错的因素的每种类型的间隔:
- 如果你表示秒或几分钟的使用1, 2, 3, 5, 10, 15, 30 (I跳过6、第12、15、20个,因为他们不要"感觉"右)。
- 如果你表现出的时间使用1, 2, 3, 4, 6, 8, 12
- 几天使用的1,2,7
- 几个星期使用1、2、4(13和26适合的模型,但是看起来太奇怪对我)
- 几个月使用1,2,3,4,6
- 多年使用1、2、5和电力的10倍
现在,这明显地开始打破你进入较大数额。当然你不想这样做显示5个星期的分,甚至在"漂亮"的时间间隔为30分钟或什么的。另一方面,当你只有48小时值得,你不想显示1天的时间间隔。的伎俩,正如你已经指出的是找到体面的过渡点。
只是预感,我会说一个合理的交叉点将是有关的两倍,因为在接下来的时间间隔。这会给你下面(最小和最大数量的间隔示之后)
- 使用几秒钟内,如果你有不到2分钟价值(为1-120)
- 使用几分钟的如果你有不少于2小时的价值(2-120)
- 使用时间,如果你有不到2日的价值(2至48)
- 使用天,如果你有不到2周的价值(2至14)
- 使用个星期,如果你有不少于2个月(2至8/9)
- 使用几个月如果你有不少于2年(2至24)
- 否则使用年(尽管你可能继续几十年,几个世纪,等等如果你的范围可以,长)
不幸的是,我们不一致的时间间隔的意思是,你结束了与一些情况下,可能有超过1百的时间间隔,而其他人已经在最8或9。所以你会想挑你的间隔比你没有超过10-15时间间隔最多(或少于5就此而言)。此外,您可以打破从一个严格定义的2倍的下一个最大的间隔时间如果你觉得它很容易跟踪。例如,可以使用时间最多3天(72小时)和几个星期长达4个月。一个小的试验和误差可能是必要的。
所以回去了,选择的时间间隔类型的尺寸您的范围,然后选择的间隔时间的尺寸通过挑选的一个"好"字,将让你与5之间的约15刻度标记。或如果你知道的和/或可以控制的实际人数象素之间的勾痕迹你可以把上限和下限有多少像素都可接受之间的壁虱(如果他们隔开的太遥远的图表可能很难阅读,但如果有太多虱子的曲线图将是混乱和标签可能重叠)。
其他提示
仍然没有回答这个问题...我会把我的第一想法,在那!我假定你有范围内的可见轴。
这可能是我会怎么做。
粗略的伪:
// quantify range
rangeLength = endOfVisiblePart - startOfVisiblePart;
// qualify range resolution
if (range < "1.5 day") {
resolution = "day"; // it can be a number, e.g.: ..., 3 for day, 4 for week, ...
} else if (range < "9 days") {
resolution = "week";
} else if (range < "35 days") {
resolution = "month";
} // you can expand this in both ways to get from nanoseconds to geological eras if you wish
在这之后,它应该(根据什么你可以很方便地访问)可以相当容易确定的价值对每一个很好的标签。根据'决议',你的格式不同的看法。E.g.:MM/DD"周",MM:SS为"距离"等, 就像你说的。
看看
http://tools.netsa.cert.org/netsa-python/doc/index.html
它有一个nice.py (python/netsa/data/nice.py ),我认为是独立的,并且应该工作的罚款。
我建议你抓住源代码gnuplot或它制(或甚至海军报),并检查它们如何处理这个问题。一般情况下是可能的N的标签应用基于宽你的阴谋,其中有些类型的'捕捉'最近'好'数字。
每次我已经写入这样的算法(太多时间真的),我已经使用的一个表中的"偏好"...即:根据时间范围的情节,决定如果我用周、天、小时,分钟等作为主要轴点。我通常包括一些优选的格式,因为我很少希望看到的日期为每分钟我绘制的图表。
我很乐意但是,惊讶地发现有人使用一个公式(如Heckbert会)以找到'好',作为变化的时间单位之间分钟、数小时、日和周的不是线性的。
[编辑-我展开这一个小小的更多 http://www.acooke.org/cute/AutoScalin0.html ]
一个天真的延长"不错的数字"算法似乎工作为基12和60,它提供了良好的间隔几个小时和分钟。这是码我只是黑客攻击在一起:
LIM10 = (10, [(1.5, 1), (3, 2), (7, 5)], [1, 2, 5])
LIM12 = (12, [(1.5, 1), (3, 2), (8, 6)], [1, 2, 6])
LIM60 = (60, [(1.5, 1), (20, 15), (40, 30)], [1, 15, 40])
def heckbert_d(lo, hi, ntick=5, limits=None):
'''
Heckbert's "nice numbers" algorithm for graph ranges, from "Graphics Gems".
'''
if limits is None:
limits = LIM10
(base, rfs, fs) = limits
def nicenum(x, round):
step = base ** floor(log(x)/log(base))
f = float(x) / step
nf = base
if round:
for (a, b) in rfs:
if f < a:
nf = b
break
else:
for a in fs:
if f <= a:
nf = a
break
return nf * step
delta = nicenum(hi-lo, False)
return nicenum(delta / (ntick-1), True)
def heckbert(lo, hi, ntick=5, limits=None):
'''
Heckbert's "nice numbers" algorithm for graph ranges, from "Graphics Gems".
'''
def _heckbert():
d = heckbert_d(lo, hi, ntick=ntick, limits=limits)
graphlo = floor(lo / d) * d
graphhi = ceil(hi / d) * d
fmt = '%' + '.%df' % max(-floor(log10(d)), 0)
value = graphlo
while value < graphhi + 0.5*d:
yield fmt % value
value += d
return list(_heckbert())
因此,举例来说,如果你想要显示秒内从0到60,
>>> heckbert(0, 60, limits=LIM60)
['0', '15', '30', '45', '60']
或者小时从0至5:
>>> heckbert(0, 5, limits=LIM12)
['0', '2', '4', '6']
在理论上也可以改变你的概念。它不是你的数据中心的可视化,但在该中心的你有你的规模。
当你知道开始和结束日期的数据,您可以创建一个规模与所有日期和分派的数据,在这个规模。像一个固定的尺度。
你可以有一个规模类型的年、月、天、小时...和限制的扩展只是这些尺度,这意味着删除这一概念的自由的扩展。
其优点是可以很容易显示出日期方面的差距。但是,如果你有一个很大的缺口,这可以成为还没有用的。