문제

날짜/시간 값 축에서 레이블을 결정하기위한 "좋은 숫자"알고리즘을 찾고 있습니다. 나는 친숙합니다 Paul 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을 사용하는 경우 (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 배수의 힘을 사용하십시오.

이제 분명히 이것은 당신이 더 많은 양으로 들어 오면서 분해되기 시작합니다. 확실히 당신은 30 분 정도의 "예쁜"간격으로도 5 주 분이 줄을 보여주고 싶지 않습니다. 반면에, 당신은 48 시간의 가치가있을 때, 당신은 1 일 간격을 보여주고 싶지 않습니다. 이미 지적한 트릭은 괜찮은 전환 지점을 찾는 것입니다.

직감에 따라 합리적인 크로스 오버 포인트가 다음 간격보다 약 2 배나 더 많을 것이라고 말할 것입니다. 그것은 당신에게 다음을 줄 것입니다 (나중에 표시된 최대 및 최대 간격 수)

  • 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

그 후에는 쉽게 액세스 할 수있는 내용에 따라 각 멋진 라벨 진드기의 값을 결정하는 것이 매우 쉬워야합니다. '해상도'에 따라 다르게 포맷합니다. 예 : "주", MM : MM : "Minute"등의 MM/DD.

살펴보십시오

http://toolsa.cert.org/netsa-python/doc/index.html

그것은 니스.py (python/netsa/data/nice.py)가있어 독립형이라고 생각하며 잘 작동해야합니다.

소스 코드를 gnuplot 또는 rrdtool (또는 플로트)으로 가져 와서이 문제에 어떻게 접근하는지 조사하는 것이 좋습니다. 일반적인 경우는 플롯의 너비에 따라 N 라벨이 적용될 수 있으며, 이는 가장 가까운 '좋은'숫자로 어떤 종류의 '스냅'을합니다.

그런 알고리즘을 작성할 때마다 (너무 많은 시간) '기본 설정'테이블을 사용했습니다 ... 즉, 플롯의 시간 범위를 기준으로, 몇 주, 며칠 동안 사용하는지 결정하십시오. 주 축 지점으로 시간, 분 등. 그래프에 표시되는 1 분마다 날짜를보고 싶지 않기 때문에 일반적으로 선호하는 서식을 포함 시켰습니다.

나는 행복 할 것이지만, 몇 분, 몇 시간, 일 및 주 사이의 시간 단위의 변동은 그렇게 선형이 아니기 때문에 (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']

이론적으로는 개념을 바꿀 수도 있습니다. 시각화의 중심에있는 데이터가 아니라 센터에는 규모가 있습니다.

데이터 날짜의 시작과 끝을 알면 모든 날짜로 척도를 생성 하고이 척도로 데이터를 발송 할 수 있습니다. 고정 스케일처럼.

연도, 월, 일, 시간, ... 스케일링을 이러한 척도로 제한하여 자유 스케일링의 개념을 제거 할 수 있습니다.

장점은 날짜 간격을 쉽게 보여줄 수 있다는 것입니다. 그러나 많은 차이가 있다면, 그것은 또한 쓸모 없게 될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top