2016-07-15 2 views
5

J'essaie de tracer un graphique à colonnes multi-axes catégorique des classements. Le classement numéro 1 devrait être la colonne la plus haute et le classement le plus bas le plus court. Essentiellement, je voudrais que la hauteur de la barre soit réciproque.Highcharts Tracer les valeurs réciproques pour la hauteur de la colonne

Il est très proche de:

var player_name_array = ["Aaron Rodgers", "Andrew Luck", "Drew Brees", "Russell Wilson", "Peyton Manning", "Ryan Tannehill", "Tony Romo", "Matt Ryan", "Cam Newton", "Ben Roethlisberger", "Eli Manning", "Philip Rivers", "Colin Kaepernick", "Teddy Bridgewater", "Marcus Mariota", "Matthew Stafford", "Robert Griffin III", "Joe Flacco", "Jay Cutler", "Sam Bradford"]; 
 

 
var series_array = [{"name":"espn_ranking","data":[38,33,63,64,67,95,75,85,96,76,999,999,999,999,999,999,999,999,999,999]}]; 
 

 
rankings_chart = new Highcharts.Chart({ 
 
     chart: { 
 
      renderTo:'rankings_chart', 
 
      type: 'column' 
 
     }, 
 
     title: { 
 
      text: 'Draft Rankings' 
 
     }, 
 
     subtitle: { 
 
      text: 'Source: The Internet' 
 
     }, 
 
     xAxis: { 
 
      categories: player_name_array, 
 
      crosshair: true 
 
     }, 
 
     yAxis: { 
 
      type: 'logarithmic', 
 
      //reversed: true, 
 
      title: { 
 
       text: 'Draft Rankings' 
 
      } 
 
     }, 
 
     tooltip: { 
 
      headerFormat: '<span style="font-size:14px"><b>{point.key}</b></span><table>', 
 
      pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + 
 
       '<td style="padding:0"><b>{point.y}</b></td></tr>', 
 
      footerFormat: '</table>', 
 
      shared: true, 
 
      useHTML: true 
 
     }, 
 
     plotOptions: { 
 
      series: { 
 
       stacking:'normal', 
 
      }, 
 
      column: { 
 
       pointPadding: 0.2, 
 
       borderWidth: 0 
 
      } 
 
     }, 
 
     rangeSelector: { 
 
      selected: 1 
 
     }, 
 
     series: series_array 
 
    });
<script src="https://code.highcharts.com/highcharts.js"></script> 
 
<div id="rankings_chart" ></div>

Le problème est les colonnes viennent du haut et le classement de 1 est toujours la plus petite colonne.

Est-il possible d'ajouter une fonction pour la hauteur de chaque colonne?

+0

Salut Bryan! pouvez-vous s'il vous plaît fournir jsfillde ou jsbin pour votre graphique? –

+0

Sure @SagarR! Voir la mise à jour. – Bryan

+0

Ce serait aussi bien si vous pouvez ajouter un dessin montrant ce que vous souhaitez réaliser. Par exemple voulez-vous obtenir quelque chose de similaire à ce tableau? http://jsfiddle.net/8yohn998/ –

Répondre

1

Étant donné que vous semblez avoir déjà fixé une limite supérieure de 999 pour vos données, je vous suggère simplement de tracer 1000-x.

Une façon de le faire est de laisser Highcharts faire le calcul en fonction de la série:

series : [{ 
     name : 'Draft Data', 
     data : (function() { 
      // generate an array of random data 
      var data = []; 

      for (var x = 0;x <= series_array.length; x += 1) { 
       data.push([ 
        1000-series_array[x]; 
       ]); 
      } 
      return data; 
     }()) 
    }] 

jsFiddle: http://jsfiddle.net/hmjnz/4/

Dans ce cas, je me cachais l'étiquette Yaxis et plutôt mettre des annotations sur les colonnes avec le rang.

Sinon, je discuterais si un graphique à colonnes est une représentation adéquate pour ce type de données.

+0

Le problème avec 1000-x est que le joueur classé numéro 1 ressemble presque au numéro 100, et leurs valeurs sont très différentes. – Bryan

+0

Bien que cela soit vrai, c'est aussi un gros problème avec vos données. Si je devais améliorer cela, je ne montrerais pas du tout les 999 joueurs, car il n'y a pas d'informations là-bas, et cela tue juste votre résolution. Mon conseil est de les sortir du tableau, de les réduire à un nombre inférieur et d'afficher les joueurs non classés (je suppose) dans une liste séparée. –

3

Définissez vos données à l'inverse du classement des joueurs:

var rankings = [38,33,63,64,67,95,75,85,96,76,999,999,999,999,999,999,999,999,999,999] 
var inv_rankings = []; 
for (i = 0; i < rankings.length; i++) { 
    inv_rankings[i] = 1/rankings[i] 
} 

Définissez vos données Highcharts être votre classement inverse:

series: { 
    name: "espn_ranking", 
    data: inv_rankings 
} 

Utilisez un formatter pour les étiquettes de données et infobulle pour retourner l'inverse de l'inverse (c'est-à-dire la valeur d'origine):

plotOptions: { 
    series: { 
     dataLabels: { 
      enabled: true, 
      formatter: function() { 
       return 1/this.y; 
      } 
     } 
    }, 
    tooltip: { 
     pointFormatter: function() { 
      return 1/this.y; 
     } 
    } 
} 

Working fiddle

2

Ce fut un puzzle intéressant et amusant à mettre en place!

Je pensais la réponse par nagyben était un excellent, et j'ai basé mon code sur leur méthode d'inverser les scores pour arriver à un rang relatif.

est ici un violon de travail que je créé sur la base de ce concept, ainsi que plusieurs améliorations, que j'ai présentées ci-après: https://jsfiddle.net/brightmatrix/j4ug40qm/

  • J'ai ajouté une fonction de tri pour classer les données dans l'ordre décroissant, peu importe comment les données ont été disposées dans les deux tableaux d'origine. Pour ce faire, j'ai d'abord combiné les deux tableaux en un seul objet Javascript.
  • J'ai changé le format en un graphique en colonne (vertical) en un diagramme en barres (horizontal). Cela rendra les noms des joueurs plus lisibles pour vos utilisateurs.
  • J'ai mis à jour l'info-bulle pour montrer le rang du joueur chaque fois qu'un utilisateur passe son curseur sur une barre particulière.
  • J'ai supprimé certains éléments de graphique qui ne sont pas nécessaires dans ce type de graphique, tels que la légende, le quadrillage et les étiquettes d'axe (puisque vous faites simplement un rang, la valeur réelle de chaque barre n'est pas pertinente l'utilisateur).

Voici le code de tri que je construit dans ce:

// combine both arrays into a single object so we can then sort them by rank 
var rankArray = []; 
$.each(player_name_array, function(index) { 
    tempArray = {}; 
    tempArray['name'] = player_name_array[index]; 
    tempArray['y'] = 1/series_array[index]; 
    rankArray.push(tempArray); 
}); 

// sort the objects by rank (the "y" value) in descending order (due to the inverse) 
// see accepted answer by Stobor at: 
// http://stackoverflow.com/questions/979256/sorting-an-array-of-javascript-objects 
rankArray.sort(function(a, b) { 
    return parseFloat(b.y) - parseFloat(a.y); 
}); 

Et voici les options graphiques mis à jour:

rankings_chart = new Highcharts.Chart({ 
    chart: { 
    renderTo:'rankings_chart', 
    type: 'bar' // chose a bar vs. column chart so the player names are easier to read 
    }, 
    title: { text: 'Draft Rankings' }, 
    subtitle: { text: 'Source: The Internet' }, 
    legend: { enabled: false }, // there is no legend needed for this chart 
    xAxis: { 
    type: 'category', 
    tickmarkPlacement: 'on' // place the lines directly on the player's name 
    }, 
    yAxis: { 
    // we're measuring by rank, so there's no need for labels, gridlines, or a title 
    labels: { enabled: false }, 
    title: { enabled: false }, 
    gridLineWidth: 0 
    }, 
    tooltip: { 
    pointFormatter: function() { 
     // show the rank of the player, based on their sort order 
     return 'ranked #' + parseInt(this.x+1); 
    } 
    }, 
    plotOptions: { 
    bar: { 
     groupPadding: 0.1, 
     pointPadding: 0.2, 
     borderWidth: 0 
    } 
    }, 
    series : [{ 
    name : 'Draft Data', 
    data : rankArray // our array will look like this: [{name: 'NAME', y: 0}, ...] 
    }] 
}); 

Voici le résultat:

enter image description here

J'espère que cela a été utile pour vous dans la conversion de votre graphique.

+1

Très belle solution! +1 – nagyben