web-dev-qa-db-fra.com

Axe vertical Google Charts en nombres entiers

J'essaie de configurer un graphique à colonnes de Google pour afficher l'axe vertical en nombres entiers, mais lorsqu'il affiche un petit nombre tel que 1, il affiche également 0,25, 0,50, etc. 

Est-ce qu'il y a une façon de changer ceci-ci? J'ai parcouru la documentation et ne trouve rien qui semble pertinent.

Merci

14
tatty27

Réponse simple: oui, mais c'est compliqué.

Si vous voulez juste que les nombres soient display sous forme de nombres entiers, alors c'est facile:

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'}}
          );
}

Si vous allez sur google playground , vous remarquerez que les étiquettes des axes sont 0, 2.5, 5, 7.5, 10. En ajoutant le format: '0' à la vAxis, seuls les nombres entiers seront affichés. devenir 0, 3, 5, 8, 10. Mais évidemment ce n’est pas idéal puisque 8 affichent comme étant à mi-chemin entre 5 et 10, ce qui n’est pas le cas, car le nombre est en réalité de 7,5 et vient d’être arrondi.

Votre capacité à modifier l'échelle/les étiquettes de l'axe est limitée. Et pour faire ce que vous demandez, il faudrait un peu de javascript spécial pour créer une échelle et un nombre de lignes de grille appropriés afin d'éviter toute décomposition en chiffres géniaux.

En gros, vous voulez vous assurer que vos valeurs maximales et minimales, ainsi que le nombre de lignes de la grille, permettent une division facile, de sorte que vous n'obtiendrez que des nombres entiers. Pour ce faire, vous devez créer une nouvelle logique géniale. Voici un exemple de code qui vous permettra d’obtenir une valeur d’axe min/max appropriée:

// 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;

Malheureusement, il y a quelques problèmes. La première est que j'utilise le nombre de lignes de la grille pour déterminer les valeurs min/max. Vous voulez savoir combien de lignes de la grille vous devez utiliser pour utiliser des nombres entiers de Nice. Je pense que la meilleure façon de procéder est la suivante (pseudo-code uniquement):

// 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
    }
}

Ensuite, vous définissez l'option gridlines (vAxis.gridlines) sur la variable ci-dessus, votre maximum sur newMax et votre min sur newMin. Cela devrait vous donner des étiquettes d'axe de nombres entiers.

Remarque: si vos nombres sont vraiment petits, la fonction ci-dessus risque de ne pas fonctionner. La fonction n’a pas non plus été testée. Veuillez donc la comparer à certains exemples de votre temps et laissez-moi savoir si cela ne fonctionne pas correctement.

24
jmac

Pour ajouter à la réponse de jmac. Si vous connaissez la valeur maximale du graphique, la solution est plus simple car en définissant maxvalue, vous pouvez vous assurer que les lignes de la grille afficheront toujours le même nombre.

Si votre contenu est très dynamique, sa solution semble être la seule.

6
Mathijs Segers

Après avoir lutté avec le même problème, je suis arrivé à des solutions très simples. Cliquez avec le bouton droit sur votre graphique, sélectionnez "édition avancée" et:

1) Définissez le nombre de lignes verticales du graphique sur "auto" (ou manuellement, égales au nombre de colonnes de données). Par la suite, Google ne doit pas calculer de points d'arrêt non entiers. A fait le tour pour moi.

2) Ou sélectionnez "Traiter les étiquettes en tant que texte", ce qui les laissera intactes.

1
The D

Je programme en Java pour générer les fichiers HTML à partir de données dynamiques et pour réutiliser la classe. J'utilise un ArrayList () pour les données et les options de la génération HTML BarChart. 

Mes données me parviennent dans un multiset de goyave qui est initialisé en tant que TreeMultiset. 

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

options = new ArrayList<String>();

Je dois m'assurer que mes articles sont en ordre, alors je fais une copie de la liste des articles. 

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

Pour chaque option dont j'ai besoin d'être dynamique, je vais ajouter une chaîne. Par exemple, key est le titre de mon graphique. 

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

La première chose que je fais est d’obtenir le plus grand nombre d’occurrences dans le multiset trié. 

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

Je veux ensuite ajouter un certain nombre de ticks à l'haxis. J'ai environ une douzaine de jeux de données. Lorsque le nombre maximal est inférieur à 100, alors cela semble agréable, mais lorsque les nombres sont en centaines ou en milliers, je dois filtrer la fonction "mod" en fonction de la valeur. 

L'autre inconvénient est que je voulais au moins une ligne au-delà de la valeur la plus grande. Je vais devoir ajuster ça aussi. 

Donc, en ajoutant la chaîne dans mes options Tableau de chaînes:

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

IntStream génère tous les nombres entre les valeurs. Max + 5 permet un dernier quadrillage à la droite de la barre la plus longue, autrement dit un plus grand que la taille de l'intervalle. Le filtre affiche uniquement les nombres modifiables par 4, intervalle que je modifierai plus tard. . Boxed () empêche les entiers d'être interprétés de manière incorrecte pour l'impression. .collect les enveloppe simplement dans un tableau String. 

Je peux ensuite simplement utiliser options.toString () pour imprimer le fort, sauf que, pour mon impression, je dois effacer les crochets de tableau de ma liste d'options, mais pas les graduations. par exemple. [ et ]. Si vous regardez ci-dessus, c'est pourquoi j'ai utilisé "<<" et ">>". 

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

La raison pour laquelle je publie cette solution est qu’elle vous donne un excellent contrôle sur l’étiquetage des axes. En dehors de la dynamique d'intervalle, ce que je ferai par la suite, cela fonctionne plutôt bien pour tous mes jeux de données. 

Voici le code HTML final qui a été imprimé. Pas les param. 

<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>
0