如何从要在 d3.scale.linear().domain() 中使用的对象数组中获取最大值

Posted

技术标签:

【中文标题】如何从要在 d3.scale.linear().domain() 中使用的对象数组中获取最大值【英文标题】:How to get maximum value from an array of objects to use in d3.scale.linear().domain() 【发布时间】:2013-04-27 06:07:45 【问题描述】:

我有一个外部 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
        );
);

【问题讨论】:

【参考方案1】:

您的 csv 文件中的数据将在您传递给 csv 函数的回调中(在您的情况下为“data”参数)。因此,您可以在 csv 函数之外定义 yScale,但如果您希望最大值依赖于数据,则需要在回调中进行设置。

至于找到最大值,许多在数组上工作的 D3 函数将接受针对您的场景的可选访问器函数。所以计算我将使用的最大值:

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

如果你想同时找到最大值和最小值,那么我建议使用 d3.extent(...) 它也应该接受一个访问器函数,并将返回一个长度为 2 的数组,其中包含最小值和最大值。

【讨论】:

感谢您的帮助。这是我的第一个问题,非常感谢提供的帮助和友好的方式。我接受了你对 Christopher Chiche 的回答,因为它不需要循环,感觉“更多 d3”。我实现了您的第二个解决方案,但必须进行两项更改才能使其正常工作,即在 d.field_goal_attempts 前面使用“+”,以便 max 返回 2000 而不是 600,并将 domain() 中的值括在方括号中。我是新手,所以我不想更改你的代码以防我错了,但我想告诉你会很好:)。再次感谢! 是的,如果将值存储为字符串,则需要在 field_goal_attempts 前面加上“+”。你对 domain 是一个数组的论点是绝对正确的!我将进行编辑。很高兴我能帮上忙! 哇,不要在开头加上 + 给了我这么多问题,你是一个救生员@Superboggly! 这个答案对我作为 d3 新手非常有帮助。我在计算嵌套数据的最大值时遇到了同样的困难。【参考方案2】:

1) 只要在计算最大值时更新函数内部的域,yScale 就可以留在d3.csv() 函数之外。例如,您可以在 d3.csv() 内部执行以下操作:

yScale.domain([0, my_max])

2) 计算最大值,这里是我常用的方法:

//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() 会很棒,但据我所知并非如此。首先计算列表然后计算最大值的优点是,如果你想计算最小值、平均值或其他任何东西,你可以做更少的计算。

【讨论】:

感谢您的帮助。这是我的第一个问题,非常感谢提供的帮助和友好的方式。我会投票赞成你的答案,但我对这样做的声誉很害羞:(。我接受了@Superbogly 的回答,因为它忽略了对 forEach 方法的需求,“感觉”“更多 d3”——听起来很糟糕,不是吗,无论如何,将“Pythonic”这个词归咎于 Python 人群 - 我对编码和 *** 都是新手,所以我只想表达我对你的回应的感激之情。谢谢 :) 不客气。他的回答确实比我的好。我通过阅读学到了新东西。

以上是关于如何从要在 d3.scale.linear().domain() 中使用的对象数组中获取最大值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 d3.scale.ordinal() 中指定域?

D3——scale

精通D3.js学习笔记比例尺和坐标

根据数据属性更改d3.js符号大小

如何从要在python中进行小波阈值处理的信号中设置阈值

d3.js - 对数刻度,范围为零和零