2013-05-02 14 views
16

Ho un file CSV esterna con i dati in colonne in questo modo:.Come ottenere il massimo valore da un array di oggetti da utilizzare in d3.scale.linear() dominio()

name, field_goal_attempts, field_goal_makes 

sto cercando usare una scala lineare ma sto incontrando difficoltà nel prendere il massimo valore per il mio dominio.

var yScale = d3.scale.linear() 
       .domain(0, d3.max(... 

Sono confuso da:

1) Se devo mettere la funzione yScale all'esterno o all'interno della funzione

d3.csv("filename.csv", function(data) { 

richiamata; e

2) Come ottenere il valore massimo degli elementi nella colonna field_goal_attempts per l'avanzamento nella funzione yScale.

Ecco il mio codice attuale:

var yScale = d3.scale.linear() 
    .domain([0, 4000]) //d3.max(data, function(d) {return d })]) 
    .range([0, 500]); 

d3.csv("test.csv", function (data) { 
    svg.selectAll("rect") 
     .data(data) 
     .enter() 
     .append("rect") 
     .attr("fill", "blue") 
     .attr("x", magic_number) // I'm not concerned about the magic numbers at this point :) 
     .attr("y", 0) 
     .attr("width", another_magic_number) 
     .attr("height", function (d) { 
      return d.field_goal_attempts 
     }) 
     .attr("id", function (d, i) { 
      return i 
     }); 
}); 

risposta

28

I dati nel file csv saranno nel callback che si passa alla funzione csv (nel caso specifico il parametro "dati"). Quindi puoi definire yScale al di fuori della funzione csv, ma se vuoi che il max sia dipendente dai dati dovrai impostarlo all'interno del callback.

Come per trovare il massimo, molte funzioni D3 che funzionano sugli array accetteranno funzioni accessorie opzionali per il proprio scenario. Quindi il calcolo della massima userei:

var max = d3.max(data, function(d) { return +d.field_goal_attempts;}); 

così si potrebbe mettere tutto insieme uno dei seguenti modi:

var yScale = d3.scale.linear().domain(0,100); 
d3.csv("test.csv", function(data){ 
    var max = d3.max(data, function(d) { return +d.field_goal_attempts;}); 
    yScale.domain([0,max]); 
    ... 
} 

o

d3.csv("test.csv", function(data){ 
    var max = d3.max(data, function(d) { return +d.field_goal_attempts;}); 
    var yScale = d3.scale.linear().domain([0,max]); 
    ... 
} 

Se si vuole trovare sia massimo e min poi suggerisco di usare d3.extent (...) che dovrebbe anche accettare una funzione accessor e restituirà un array di lunghezza 2 con i valori min e max.

+1

Grazie per l'aiuto. Questa è la mia prima domanda e sono grato per l'aiuto e il modo amichevole con cui è stato consegnato. Ho accettato la tua risposta su Christopher Chiche perché sentiva "più d3" non richiedendo un loop. Ho implementato la tua seconda soluzione, ma ho dovuto fare due modifiche per farlo funzionare, ovvero usare '+' davanti a d.field_goal_attempts in modo che max restituisse 2000 e non 600, e di racchiudere i valori in domain() tra parentesi quadre. Sono nuovo quindi non voglio cambiare il tuo codice in caso mi sbagli, ma ho pensato che sarebbe stato bello dirti :). Grazie ancora! – Emil

+0

Sì, è necessario il '+' davanti a field_goal_attempts se il valore è memorizzato come stringa. E hai assolutamente ragione sull'argomento del dominio come array! Farò le modifiche. Felice di poterti aiutare! – Superboggly

+0

Wow non aggiungendo che + all'inizio mi dava così tanti problemi, sei un risparmiatore di vita @Superboggly! –

1

1) Il yScale può rimanere al di fuori della funzione d3.csv() fino a quando si aggiorna il dominio interno della funzione quando dopo aver calcolato il massimo. Per esempio si potrebbe fare quanto segue all'interno di d3.csv():

yScale.domain([0, my_max]) 

2) Per calcolare il massimo, qui è il metodo che di solito uso:

//Create list containing only field_goal_attempts 
field_goal_attempts_list = data.forEach(function(d){return d.field_goal_attempts}) 

//Compute max using d3.max() function 
field_goal_attempts_max = d3.max(field_goal_attempts_list) 

E 'vero che il passaggio tale funzione a d3.max() sarebbe essere grandioso ma per quanto ne so non lo è. Il vantaggio di calcolare prima l'elenco e quindi calcolare il massimo è che si eseguono meno calcoli se si desidera calcolare il minimo, la media o qualsiasi altra cosa.

+0

Grazie per l'aiuto. Questa è la mia prima domanda e sono grato per l'aiuto e il modo amichevole con cui è stato consegnato. Voterò la tua risposta, ma sono timido sulla reputazione di farlo :(. Ho accettato la risposta di @ Superbogly perché 'sente' 'd3' ignorando la necessità del metodo forEach - sembra terribile, non è vero? incolpare la folla di Python per il termine "Pythonic", comunque - Sono nuovo sia per la codifica che per StackOverflow, quindi voglio solo esprimere il mio apprezzamento per la vostra risposta.Grazie :) – Emil

+0

Sei il benvenuto. La sua risposta è davvero migliore della mia. Ho imparato una cosa nuova leggendolo. –

Problemi correlati