2016-07-15 107 views
5

Sto provando a tracciare un grafico a colonne multiassiale categoriale di classifiche. La classifica numero 1 dovrebbe essere la colonna più alta e quella più bassa quella più corta.Diagrammi Highcharts Valori reciproci per altezza colonna

In sostanza vorrei che l'altezza della barra fosse reciproca.

è molto vicino a:

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>

Il problema di questo è le colonne scendono dalla parte superiore e classifica del 1 è ancora la colonna più piccola.

C'è un modo per aggiungere una funzione per l'altezza di ogni colonna?

+0

Ciao Bryan! puoi fornire jsfillde o jsbin per il tuo grafico? –

+0

Sure @SagarR! Guarda l'aggiornamento. – Bryan

+0

Sarebbe anche bello se fosse possibile aggiungere un disegno che mostra cosa si desidera ottenere. Ad esempio, ti piacerebbe avere qualcosa di simile a questo grafico? http://jsfiddle.net/8yohn998/ –

risposta

1

Poiché sembra che sia già stato impostato un limite superiore di 999 per i dati, suggerirei semplicemente di tracciare 1000 x.

Un modo per farlo è quello di lasciare che Highcharts fare la matematica in una funzione per la serie:

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/

In questo caso mi nascondevo l'etichetta asseY e invece mettere annotazioni sulle colonne con il rango.

In alternativa vorrei discutere se un grafico a colonne è una rappresentazione adeguata per questo tipo di dati.

+0

Il problema con 1000-x è che il giocatore con il numero 1 sembra quasi lo stesso del numero 100 ei loro valori sono molto diversi. – Bryan

+0

Anche se questo è vero, è anche un grosso problema con i tuoi dati. Se dovessi farlo, non visualizzerei affatto i 999 giocatori, dato che non ci sono informazioni lì e uccide solo la tua risoluzione. Il mio consiglio è portarli fuori dal grafico, ritagliare un numero inferiore e mostrare i giocatori non classificati (presumo) in un elenco separato. –

3

impostare i propri dati per essere l'inverso della classifica giocatore:

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

Impostare i dati Highcharts di essere il vostro ranking inversa:

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

Utilizzare un formattatore per le etichette di dati e tooltip per restituire il reciproco del reciproco (cioè il valore originale):

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

Working fiddle

2

Questo è stato un puzzle interessante e divertente da risolvere!

Ho pensato che la risposta di nagyben era eccellente e ho basato il mio codice sul loro metodo di inversione dei punteggi per ottenere un rango relativo.

Ecco un violino di lavoro ho creato sulla base di questo concetto, insieme a diversi miglioramenti, che ho condiviso qui di seguito: https://jsfiddle.net/brightmatrix/j4ug40qm/

  • Ho aggiunto una funzione di ordinamento per classificare i dati in ordine decrescente, non importa come i dati sono stati disposti nei due array originali. Per fare questo, ho prima combinato entrambi gli array in un singolo oggetto Javascript.
  • Ho modificato il formato in una colonna (verticale) in un grafico a barre (orizzontale). Ciò renderà i nomi dei giocatori più leggibili per i tuoi utenti.
  • Ho aggiornato il suggerimento per mostrare il grado del giocatore ogni volta che un utente alza il cursore su una determinata barra.
  • Ho rimosso alcuni elementi del grafico che non sono necessari in questo tipo di grafico, come la legenda, la griglia e le etichette degli assi (dato che stai semplicemente facendo un rank, il valore reale di ogni barra non è rilevante per l'utente).

Ecco il codice tipo che ho costruito in questo:

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

ed ecco le opzioni grafico aggiornato:

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}, ...] 
    }] 
}); 

Ecco il risultato:

enter image description here

Spero che sia stato utile per te nella conversione del tuo grafico.

+1

Soluzione molto bella! +1 – nagyben