динамическое масштабирование dcjs для соответствия диапазону значений - PullRequest
1 голос
/ 19 сентября 2019

У меня есть таблица строк в DCjs, которая отображает верхние значения N данного параметра.Однако для нефильтрованных данных они отличаются друг от друга очень маленьким числом.

Accounts plotted with no filters, account ID and full range

Мне пришлось пометить каждую строку своим уникальным идентификаторомТак как мой генератор случайных чисел произвел два идентичных имени, это означает, что если я использую имя в качестве измерения, я получу одну из десяти тысяч точек данных, значение которых превышает 100%.

Однако основная проблема здесь в том, что разница между каждой строкой крошечная и может составлять около 0,0001.

Однако, если я увеличу эту часть оси X, используя

var max = dim.top[1][0].value;
var min = dim.top(10)[9].value;    

chart
  .dimension(dim)
  .group(group)
  .x(d3.scaleLinear()
     .range([-100, chart.width()])
     .domain([min-(max-min)*0.1,max])
  )
  .cap(10)
  .othersGrouper(null)
  .colors(['#ff0000']);

enter image description here

Сначала я теряю идентификационную метку слева.Во-вторых, поскольку я также должен использовать .elasticX (false) для увеличения, это означает, что когда я добавляю фильтры, диапазон оси x не изменяется со значениями, например

enter image description here

Есть ли способ получить динамическое масштабирование, чтобы диапазон оси x зависел от диапазона представленных значений?

1 Ответ

2 голосов
/ 19 сентября 2019

elasticX - это действительно простая функция, которая в значительной степени выполняет то, что делает ваш код, хотя она фиксирует мин или макс в ноль в зависимости от положительных или отрицательных данных:

        var extent = d3.extent(_rowData, _chart.cappedValueAccessor);
        if (extent[0] > 0) {
            extent[0] = 0;
        }
        if (extent[1] < 0) {
            extent[1] = 0;
        }

( calcAxisScale source )

Этот код вызывается (косвенно) перед каждым рендерингом и перерисовкой.

Вот несколько советов общего назначения, когда elasticX или elasticY делает не совсем то, что вы хотите.Я никогда не видел, чтобы это провалилось!(Который говорит что-то в такой причудливой кодовой базе, как dc.js.)

Сначала отключите elasticX.Затем создайте функцию, которая вычисляет домен X и задает его:

function custom_elastic(chart) {
  var max = chart.dimension().top[1][0].value;
  var min = chart.dimension().top(10)[9].value;
  chart.x().domain([min,max]);
}

Я настроил его на диаграмме для общности.

Теперь мы можем вызвать эту функцию для события preRender и preRedraw .Эти события будут проходить по графику при срабатывании:

chart.on('preRender', custom_elastic)
     .on('preRedraw', custom_elastic);

И это должно быть сделано!

Кстати, вы, вероятно, не хотите устанавливать диапазон шкалы - это установленоавтоматически по графику, и это немного сложнее, чем у вас, поскольку он учитывает поля.

Отладка мин и макс

Просмотр вашей скрипки IЯ понял, что я не дал второго взгляда на то, как вы рассчитываете минимальное и максимальное значения.

Я также не заметил, что у вас диапазон начинается с -100.

Хорошо сначалапошаговое ведение журнала;он сообщает

min: 0.81, max: 0.82

, что неверно.Верхние десять находятся в диапазоне от 0,96 до 1.

Проблема заключается в том, что ключом измерения является id, поэтому строки, возвращаемые .top(), расположены в обратном алфавитном порядке («самые большие» строки).

Опять вы на правильном пути с

console.log(Group.top(Infinity))

Да!Группа даст вам 10 лучших по значению.

var top10 = thischart.group().top(10);
var max = top10[0].value;
var min = top10[9].value;

Отлично!

semi-working bar elastic

скрипка

Но подождите, разве это не похоже на то, что бары растягиваются с левой стороны графика?

Хакинг линейного графика с помощью renderlet для рисования баров начиная с левого края

Хорошо, теперь ясно, что линейный график не поддерживает это.Вот хак, чтобы изменить размеры столбцов к левому краю:

chart.on('renderlet', function(chart) {
    var transform = chart.select('g.row rect').attr('transform');
    var tx = +transform.split('(')[1].split(',')[0];
    chart.selectAll('g.row rect')
        .attr('transform', null)
        .attr('width', function(d) {
            return +d3.select(this).attr('width') + tx;
        })
    chart.selectAll('g.row text.row')
        .attr('transform', null);    
})

Все ряды строк будут смещены большим отрицательным числом, которое мы сначала захватим в tx.Затем мы удаляем transform как из текстов, так и из текста, и добавляем tx к ширине рядов.

good except for the last bar

скрипка

Отлично!Но где последний бар?Итак, мы взяли первые десять значений для минимального и максимального значений, поэтому десятый столбец - это минимальное значение.

Вы должны выяснить, что работает для вас, но я обнаружил, что, глядя на верхние 20значения оставили 10 лучших при хороших размерах:

var N = 20;
var topN = thischart.group().top(N);
var max = topN[0].value;
var min = topN[N-1].value;

good bounds

конечная скрипка

Этот хак делаетне очень хорошо работают со встроенными переходами, поэтому я отключил их для этого графика:

chart.transitionDuration(0)

Было бы гораздо больше работы, чтобы взломать эту часть, и лучше исправить ее вСам график .

...