Вертикальная ось Google в целых числах

Я пытаюсь настроить диаграмму столбцов Google, чтобы отображать вертикальную ось в целых числах, но когда она отображает небольшое число, такое как 1, отображающее 0,25, 0,50 и т.д.

Есть ли способ изменить это? Я прошел через документацию и не могу найти ничего, что кажется актуальным.

Спасибо

Ответ 1

Простой ответ: да, но это сложно.

Если вы просто хотите, чтобы числа отображались как целые числа, тогда легко:

function drawVisualization() {
  // Create and populate the data table.
  var data = google.visualization.arrayToDataTable([
    ['x', 'Cats', 'Blanket 1', 'Blanket 2'],
    ['A',   1,       1,           0.5],
    ['B',   2,       0.5,         1],
    ['C',   4,       1,           0.5],
    ['D',   8,       0.5,         1],
    ['E',   7,       1,           0.5],
    ['F',   7,       0.5,         1],
    ['G',   8,       1,           0.5],
    ['H',   4,       0.5,         1],
    ['I',   2,       1,           0.5],
    ['J',   3.5,     0.5,         1],
    ['K',   3,       1,           0.5],
    ['L',   3.5,     0.5,         1],
    ['M',   1,       1,           0.5],
    ['N',   1,       0.5,         1]
  ]);

  // Create and draw the visualization.
  new google.visualization.LineChart(document.getElementById('visualization')).
      draw(data, {curveType: "function",
                  width: 500, height: 400,
                  vAxis: {maxValue: 10, format: '0'}}
          );
}

Если вы перейдете на страницу google playground, вы заметите, что метки оси - 0, 2.5, 5, 7.5, 10. Добавив формат: '0' в vAxis, он будет отображать только целые числа, поэтому мои ярлыки становятся 0, 3, 5, 8, 10. Но, очевидно, это не идеально, так как 8 отображается как на полпути между 5 и 10, что не является " t, потому что число фактически равно 7.5 и просто округлено.

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

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

// Take the Max/Min of all data values in all graphs
var totalMax = 345;
var totalMin = -123;

// Figure out the largest number (positive or negative)
var biggestNumber = Math.max(Math.abs(totalMax),Math.abs(totalMin));

// Round to an exponent of 10 appropriate for the biggest number
var roundingExp = Math.floor(Math.log(biggestNumber) / Math.LN10);
var roundingDec = Math.pow(10,roundingExp);

// Round your max and min to the nearest exponent of 10
var newMax = Math.ceil(totalMax/roundingDec)*roundingDec;
var newMin = Math.floor(totalMin/roundingDec)*roundingDec;

// Determine the range of your values
var range = newMax - newMin;

// Define the number of gridlines (default 5)
var gridlines = 5;

// Determine an appropriate gap between gridlines
var interval = range / (gridlines - 1);

// Round that interval up to the exponent of 10
var newInterval = Math.ceil(interval/roundingDec)*roundingDec;

// Re-round your max and min to the new interval
var finalMax = Math.ceil(totalMax/newInterval)*newInterval;
var finalMin = Math.floor(totalMin/newInterval)*newInterval;

Здесь есть пара вопросов (к сожалению). Во-первых, я использую количество линий сетки для определения значений min/max - вы хотите выяснить, сколько линий сетки вам нужно использовать для приятных целых чисел. Самый простой способ сделать это, я думаю, будет следующим образом (только псевдокод):

// Take the Max/Min of all data values in all graphs
var totalMax = 3;
var totalMin = -1;

// Figure out the largest number (positive or negative)
var biggestNumber = Math.max(Math.abs(totalMax),Math.abs(totalMin));

// Round to an exponent of 10 appropriate for the biggest number
var roundingExp = Math.floor(Math.log(biggestNumber) / Math.LN10);
var roundingDec = Math.pow(10,roundingExp);

// Round your max and min to the nearest exponent of 10
var newMax = Math.ceil(totalMax/roundingDec)*roundingDec;
var newMin = Math.floor(totalMin/roundingDec)*roundingDec;

// Determine the range of your values
var range = newMax - newMin;

// Calculate the best factor for number of gridlines (2-5 gridlines)
// If the range of numbers divided by 2 or 5 is a whole number, use it
for (var i = 2; i <= 5; ++i) {
    if (Math.round(range/i) = range/i) {
        var gridlines = i
    }
}

Затем вы установите параметр сетки (vAxis.gridlines) в указанную выше переменную, а ваш max - newMax, а ваш min - в newMin. Это должно дать вам целые метки оси.

Примечание. Если ваши номера действительно малы, то вышеуказанная функция может не работать. Функция также не проверена, поэтому, пожалуйста, проверьте ее на некоторых примерах в свое время и сообщите мне, если она не работает должным образом.

Ответ 2

Просто чтобы расширить ответ Jmac. Если вы знаете максимальное значение диаграммы, решение простое, если maxvalue гарантирует, что вы всегда будете использовать одну и ту же высоту для диаграммы.

Если ваш контент очень динамичный, его решение кажется единственным.

Ответ 3

После борьбы с одной и той же проблемой я пришел к очень простым решениям. Щелкните правой кнопкой мыши диаграмму, выберите "расширенное редактирование" и:

1) Установите количество вертикальных линий для диаграммы на "авто" (или вручную равное количеству столбцов данных) - впоследствии Google не должен вычислять нецелые точки останова. Сделал трюк для меня.

2) Или выберите "Обработать ярлыки как текст", который оставит их нетронутыми.

Ответ 4

Я программирую на Java для генерации HTML файлов на основе динамических данных и повторного использования класса. Я использую ArrayList() как для данных, так и для части параметров генерации HTML BarChart.

Мои данные поступают ко мне в Guava Multiset, который инициализируется как TreeMultiset.

Multiset<String> items = TreeMultiset.create();

options = new ArrayList<String>();

Мне нужно убедиться, что мои товары в порядке, поэтому я делаю копию списка товаров.

Multiset<String> occurrences = Multisets.copyHighestCountFirst(items);

Для каждого варианта, который мне нужен, я добавлю строку. Например, ключ - это заголовок моего графика.

options.add("\n      title : '"+key+"'");

Первым делом я получаю наибольшее количество вхождений в отсортированном мультисети.

int max = occurrences.count(Iterables.get(occurrences,  0));

Затем я хочу добавить некоторое количество галочек к оси. У меня есть около десятка наборов данных. Когда максимальные числа меньше 100, это выглядит хорошо, но когда числа исчисляются сотнями или тысячами, мне нужно отфильтровать функцию "мод" на основе значения.

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

Итак, добавив строку в мой массив параметров String:

options.add("\n         hAxis : { title : 'Count', ticks: <<"+      
          IntStream.range(0, max+5)
                   .filter(x -> x % 4 == 0)
                   .boxed()
                   .collect(Collectors.toList())
         +">> }");      

IntStream генерирует все числа между значениями. max + 5 позволяет одну последнюю линию сетки справа от самого длинного бара, то есть на один больше, чем размер интервала. Фильтр показывает только числа, которые можно изменить на 4, мой интервал, который я отрегулирую позже. .boxed() предотвращает неправильную интерпретацию целых чисел для печати. .collect просто упаковывает их в массив String.

Затем я могу просто использовать options.toString() для печати сильного, за исключением того, что для печати мне нужно убрать скобки массива в моем списке параметров, но не галочки. например [ а также ]. Если вы посмотрите выше, вот почему я использовал "& lt; & lt;" и ">>".

  String optionstr = stripBrackets(options.toString())
                          .replaceAll("<<", "[")
                          .replaceAll(">>", "]");

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

Вот последний HTML, который был распечатан. Не в скобках параметр клещей.

<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load('current', {'packages':['corechart']});
      google.charts.setOnLoadCallback(drawVisualization);

      function drawVisualization() {
        var data = google.visualization.arrayToDataTable([
          [ 'Signals', 'Count', { role: 'style' }], 
          [ 'Agreements' , 6, 'blue' ], 
          [ 'ProductsMarkets' , 3, 'blue' ], 
          [ 'DebtEquity' , 1, 'blue' ], 
          [ 'Executive' , 1, 'blue' ], 
          [ 'Securities' , 1, 'blue' ]]);

    var options = {
         title : 'Signals', 
         vAxis : { title : 'Signals' }, 
         hAxis : { title : 'Count', ticks: [0, 4, 8] }, 
         bars: 'horizontal', 
         bar : { groupWidth : "95%" }, 
         legend : { position : "none" }
    };

    var chart = new google.visualization.BarChart(document.getElementById('signals'));
    chart.draw(data, options);
    }
    </script>
  </head>
  <body>
    <div id="signals" style="width: 900px; height: 500px;"></div>
  </body>
</html>