Как получить максимальное значение из массива объектов для использования в d3.scale.linear(). Domain() - программирование
Подтвердить что ты не робот

Как получить максимальное значение из массива объектов для использования в d3.scale.linear(). Domain()

У меня есть внешний файл csv с данными в таких столбцах:

name, field_goal_attempts, field_goal_makes

Я пытаюсь использовать линейный масштаб, но сталкиваюсь с трудностями получения максимального значения для моего домена.

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

Я смущен относительно:

1) Должен ли я использовать функцию yScale вне или внутри

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

функция обратного вызова; и

2) Как получить максимальное значение элементов в столбце field_goal_attempts, чтобы затем передать функцию yScale.

Вот мой код в настоящее время:

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
        });
});
4b9b3361

Ответ 1

Данные в вашем файле csv будут в обратном вызове, который вы передадите функции csv (в вашем случае параметр "data" ). Таким образом, вы можете определить yScale вне функции csv, но если вы хотите, чтобы max был зависимым от данных, вам нужно будет установить его внутри обратного вызова.

Что касается поиска max, многие функции D3, работающие на массивах, будут принимать дополнительные функции доступа для вашего сценария. Поэтому, вычисляя max, я бы использовал:

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

Итак, вы можете собрать все это одним из двух способов:

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

или

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

Если вы хотите найти как max, так и min, я предлагаю использовать d3.extent(...), который также должен принять функцию accessor и вернет массив длиной 2 с минимальными и максимальными значениями.

Ответ 2

1) yScale может оставаться вне функции d3.csv(), пока вы обновляете домен внутри функции при вычислении max. Например, вы можете сделать следующее внутри d3.csv():

yScale.domain([0, my_max])

2) Чтобы вычислить max, здесь используется метод, который я обычно использую:

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

Верно, что передача такой функции в d3.max() была бы большой, но насколько я знаю, это не так. Преимущество первого вычисления списка и последующего вычисления max заключается в том, что вы выполняете меньше вычислений, если хотите вычислить min, mean или something else.