2012-03-13 12 views
6

Jestem nowy w D3 i bawię się z rozrzutu. Nie mogę uzyskać d3.max (danych), aby działał poprawnie podczas konfigurowania domeny!Dlaczego domena nie używa d3.max (danych) w D3?

Mam następujący konfigurowania zestawu danych losowych:

var data = []; 
     for (i=0; i < 40; i++){ 
      data.push({"x": i/40, "y": i/8, "a": Math.floor(Math.random() * 3), "x2": Math.random()}); 
     } 

I wtedy następujące ustawić moje współrzędne:

var x = d3.scale.linear().domain([0, 1]).range([0 + margin, w-margin]), 
      y = d3.scale.linear().domain([0, d3.max(data)]).range([0 + margin, h-margin]), 
      c = d3.scale.linear().domain([0, 3]).range(["hsl(100,50%,50%)", "rgb(350, 50%, 50%)"]).interpolate(d3.interpolateHsl); 

Stawia wszystkie 40 punktów w jednej, poziomej linii. Jeśli zamieniam d3.max (dane) na "5", to jest to przekątna (aczkolwiek od górnej lewej do prawej dolnej strony wciąż mam problemy z odwróceniem współrzędnych y). Dlaczego d3.max (dane) nie działają zgodnie z oczekiwaniami?

Odpowiedz

9

d3.max() oczekuje tablicy liczb, a nie obiektów. Elementy data mają wewnętrzną strukturę klucz-wartość i nie ma sposobu, aby d3.max() wiedzieć, co wziąć maksimum. Możesz użyć czegoś takiego, jak jQuery's $.map, aby uzyskać elementy żądanych obiektów, a następnie przyjąć maksimum, np.

var maxy = d3.max($.map(data, function(d) { return d.y; })); 

Edit:

Jak podkreślono w komentarzu poniżej, nie trzeba nawet JQuery do tego, jak .map() jest rodowitym metoda Array. Następnie kod staje się po prostu

var maxy = d3.max(data.map(function(d) { return d.y; })); 

lub nawet prostsze (i dla tych przeglądarek, które nie wdrażają Array.map()), stosując opcjonalny drugi argument d3.max, który mówi, że jak uzyskać dostęp do wartości w tablicy

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

Nie potrzebujesz jQuery do mapowania; jest to natywna metoda Array: 'd3.max (data.map (function (d) {return d.y;}))'. 'd3.max()' przyjmuje opcjonalny akcesor jako swój drugi argument, więc możesz również zrobić 'd3.max (dane, funkcja (d) {return d.y;})) –

3

d3.max Dokumentacja API znajduje się pod numerem here.

# d3. maks (Tablica [, dostępowe])

Zwraca maksymalną wartość danej tablicy przy użyciu naturalnych zamówienia. Jeśli tablica jest pusta, zwraca niezdefiniowaną. Opcjonalna funkcja dostępowa może zostać określona, ​​co jest równoważne wywołaniu array.map (accessor) przed obliczeniem wartości maksymalnej. W przeciwieństwie do wbudowanego Math.max, ta metoda ignoruje niezdefiniowane wartości; przydaje się to do obliczania domeny skali, a jednocześnie uwzględnia tylko określony region danych . Ponadto elementy porównywane są przy użyciu porządku naturalnego, a nie w kolejności numerycznej. Na przykład, maksymalna [ "20", "3"] jest "3", natomiast maksymalna [20, 3] 20.

Stosując tę ​​informację do pierwotnego pytania otrzymujemy:

function accessor(o){ 
    return o.y; 
} 
var y = d3.scale.linear() 
     .domain([0, d3.max(data, accessor)]) 
     .range([0 + margin, h-margin]); 

Jeśli w końcu będziesz korzystać z wielu funkcji akcesora, możesz po prostu zrobić fabrykę.

function accessor(key) { 
    return function (o) { 
     return o[key]; 
    }; 
} 
var x = d3.scale.linear() 
     .domain([0, d3.max(data, accessor('x'))]) 
     .range([...]), 
    y = d3.scale.linear() 
     .domain([0, d3.max(data, accessor('y'))]) 
     .range([...]); 
0

Miałem podobny problem dotyczący tablicy asocjacyjnej. Moje dane wyglądały następująco: [{"year_decided": 1982, "total": 0}, {"year_decided": "1983", "Total": "847"}, ...}]

Po prostu przekazywanie parseInt przed zwróceniem wartości działa.

var yScale = d3.scale.linear() 
    .domain([0, d3.max(query,function(d){ return parseInt(d["Total"]); }) ]) 
    .range([0,h]);