Закрыть

Для эффективной работы на сайте используются cookie и обработка персональных данных. Пользуясь этим сайтом, вы соглашаетесь с правилами использования сайта. Подробнее

Цитата дня

Группировка данных в зависимости от выбранного интервала времени в highstock

15 октября 2017 г. 10:17

Как оказалась, в графиках highstock не особо гибкая настройка группировки точек в зависимости от просматриваемого интервала времени. Да, данные могут группироваться, если их очень много (более тысячи) в некотором выбранном отрезке времени. Но когда это произойдёт, точно не понятно.

Настройку группировки вы можете осуществить через параметр plotOptions.series.dataGrouping.units ( http://api.highcharts.com/highstock/plotOptions.series.dataGrouping.units ), например:

Highcharts.stockChart('chart', {

    plotOptions: {
        series: {
            dataGrouping: {
                forced: true,
                units: units: [[ 'week', [1] ], ]
            },
        }
    },

    ...
});

Но здесь не указывается при каком временном определённом интервале следует выполнять соответствующую группировку (по неделям, месяцам и т. д.).

Для моего графика посещаемости этого сайта (который находится на странице Новости ) для удобства анализа данных нужно было группировать точки в неделю только тогда, когда выбранный временной интервал составлял не менее 3 месяцев. Посмотрите в действии:

Сегодня За последний месяц
Посетители 96 5712
Визиты 102 6578
Просмотры 168 9833

Чтобы управлять группировкой данных, я добавил функцию setExtremes ( http://api.highcharts.com/highstock/xAxis.events.setExtremes ), которая вызывается при изменении временного интервала:

var time_break = 3 * 31 * 24 * 3600 * 1000;

Highcharts.stockChart('chart', {
    xAxis: {
        ...
        events: {
             setExtremes: function (e) {
                 delta = e.max - e.min;
                 if (delta <= time_break) {
                     $.each(this.series, function (index, obj) {
                         obj.options.dataGrouping.units[0] = ['day', [1]];
                     });
                 } else {
                     $.each(this.series, function (index, obj) {
                         obj.options.dataGrouping.units[0] = ['week', [1]];
                     });
                 }
             }
         }
    },

    ...
});

Как я говорил, параметр obj.options.dataGrouping.units отвечает за группировку наших точек. Чтобы посчитать временной интервал, нужно от конечной временной точки отнять начальную: e.max - e.min, а затем полученную разность сравнить с 3 месяцами. Разница e.max - e.min определяется в миллисекундах, поэтому подсчитываем сколько будет 3 месяца в миллисекундах и записываем это значение в time_break. Если time_break меньше 3-х месяцев, то устанавливаем значение ['day', [1]] в obj.options.dataGrouping.units[0], иначе ['week', [1]].

И напоследок, приведу полный листинг кода этого графика:

var time_break = 3 * 31 * 24 * 3600 * 1000;

Highcharts.stockChart('chart_{{ instance.id }}', {
    chart: {
        zoomType: 'x'
    },

    title: {
        text: '{% trans 'Visitors of vivazzi.ru' %}'
    },

    subtitle: {
        text: '{% trans 'Based on Yandex.Metrika' %}'
    },

    rangeSelector : {
        selected : 0,
        buttons: [{
            type: 'month',
            count: 1,
            text: '1{% trans 'm' %}'
        }, {
            type: 'month',
            count: 3,
            text: '3{% trans 'm' %}'
        }, {
            type: 'month',
            count: 6,
            text: '6{% trans 'm' %}'
        }, {
            type: 'year',
            count: 1,
            text: '1{% trans 'y' %}'
        }],
        inputDateFormat: '{% if request.LANGUAGE_CODE == 'ru' %}%e %b %Y{% else %}%b %e, %Y{% endif %}'
    },


    xAxis: {
        type: 'datetime',
        events: {
             setExtremes: function (e) {
                 delta = e.max - e.min;
                 if (delta <= time_break) {
                     $.each(this.series, function (index, obj) {
                         obj.options.dataGrouping.units[0] = ['day', [1]];
                     });
                 } else {
                     $.each(this.series, function (index, obj) {
                         obj.options.dataGrouping.units[0] = ['week', [1]];
                     });
                 }
             }
         }
    },

    yAxis: {
        title: {
            text: '{% trans 'Number' %}'
        }
    },

    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle'
    },

    plotOptions: {
        series: {
            tooltip: {
                valueDecimals: 0
            },

            dataGrouping: {
                dateTimeLabelFormats: {
                   millisecond: ['%A, %b %e, %H:%M:%S.%L', '%A, %b %e, %H:%M:%S.%L', '-%H:%M:%S.%L'],
                   second: ['%A, %b %e, %H:%M:%S', '%A, %b %e, %H:%M:%S', '-%H:%M:%S'],
                   minute: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'],
                   hour: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'],
                   day: ['{% if request.LANGUAGE_CODE == 'ru' %}%A, %e %b %Y{% else %}%A, %b %e, %Y{% endif %}', '%A, %b %e', '-%A, %b %e, %Y'],
                   week: ['{% trans 'Average value in week from' %} {% if request.LANGUAGE_CODE == 'ru' %}%e %b %Y{% else %}%b %e, %Y{% endif %}', '%A, %b %e', '-%A, %b %e, %Y'],
                   month: ['%B %Y', '%B', '-%B %Y'],
                   year: ['%Y', '%Y', '-%Y']
                },

                forced: true,
                units: [
                    ['day', [1]]
                ]
            },

            pointStart: Date.UTC({{ start_year }}, {{ start_month }}, {{ start_day }}),
            pointInterval: 24 * 3600 * 1000 // one day
        }
    },

    series: {{ values }}
});
Примечание:
В фигурных скобках используются django-переменные. Что они выводят - интуитивно понятно, поэтому расписывать не буду.

Оцените статью

5 из 5 (всего 1 оценка)

Поля, отмеченные звёздочкой ( * ) , являются обязательными.

Спасибо за ваш отзыв!

Автор статьи

Права на использование данной статьи, расположенной на настоящей странице http://vivazzi.ru/it/data-grouping-highstock/:

Разрешается копировать статью с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор статьи: Мальцев Артём
Ссылка на статью: <a href="http://vivazzi.ru/it/data-grouping-highstock/">http://vivazzi.ru/it/data-grouping-highstock/</a>

Подробнее: Правила использования сайта

Вам нужно саморазвиваться или вы хотите зарабатывать деньги?

Или вы ищите хорошие IT сервисы или книги? Сохраните свое время и взгляните на мою подборку рекомендаций, которыми постоянно пользуюсь.
Посмотреть рекомендации

Комментариев: 3

Николай
Николай

17.11.2017 8:35 #

Ответить

Артём Мальцев
Артём Мальцев автор

17.11.2017 23:16 #

Да, есть такое решение. Мне оно не понравилось, потому что группировка происходит только по клику кнопок зума. Если передвигать ползунок временной шкалы, то группировка сбивается.

Ответить

Николай
Николай

29.11.2017 9:39 #

Да, действительно сбивается группировка при использовании ползунка. Спасибо

Ответить

Вы можете оставить комментарий как незарегистрированный пользователь. Но, зарегистрировавшись, вы сможете получать оповещения об ответах, а также иметь доступ к своему личному аккаунту для просмотра своих комментариев.

Чтобы оставить комментарий от своего имени войдите или зарегистрируйтесь обычным способом или через социальные сети:

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте