使用D3.js时,是否有一种方法可以自动获取最接近的包含数据的“key”?

使用D3.js时,是否有一种方法可以自动获取最接近的包含数据的“key”?,d3.js,D3.js,当我们使用D3.js时,为了简单起见,我们有数据,即股票价格: 2021-03-18 $38.10 2021-03-19 $38.60 2021-03-22 $38.80 我们用D3绘制一个股价折线图,然后移动鼠标在价格上方“悬停”,它会显示该日期的价格 现在我正在使用 d3.select("svg").on("mousemove", (ev) => { const hour = xScale.invert(ev.offsetX -

当我们使用D3.js时,为了简单起见,我们有数据,即股票价格:

2021-03-18   $38.10
2021-03-19   $38.60
2021-03-22   $38.80
我们用D3绘制一个股价折线图,然后移动鼠标在价格上方“悬停”,它会显示该日期的价格

现在我正在使用

d3.select("svg").on("mousemove", (ev) => {
  const hour = xScale.invert(ev.offsetX - dimensions.margin.left).getHours();
获取用户悬停的时间。
xScale
是从域到范围的缩放函数
scaleTime()
,而
xScale.invert
是将范围转换回域的函数

如果时间是下午12点或更晚,我认为它是第二天,如果它在之前或相等,我认为是同一天。这是因为2021-03-19的股票价格被认为是在凌晨12:00(午夜),因此,如果我到达晚上9点,例如,鼠标光标实际上接近第二天

  • 然后,假设我确定它是
    2021-03-20
    ,然后我检查是否有股价数据。但由于这是一个星期六,没有股票数据,我使用一个函数通过以下方法进行检查:

  • 我首先会回到
    2021-03-19
    ,看看是否有股价。(我首先构建一个查找表,将日期映射到数据)。如果有,就用它

  • 但如果没有,我只使用1天的
    增量
    ,然后越走越远,这样它会转到
    2021-03-21
    ,然后增加增量,使用
    -delta
    检查
    2021-03-18
    ,所以我只使用一个点,然后在增量增加的情况下转到“以后”和“之前”,直到我能够找到价格

  • 换言之,我有“第一个候选人”和“第二个候选人”。如果第一个候选人有数据,那么就使用它。否则,请尝试第二个候选人。如果仍然不工作,则从第一个候选人开始工作,并使用1天的增量,然后移动到“以后”或“之前”,如果不工作,则使用2天和3天的增量,直到我能够找到包含数据的日期

  • 然后我用这个价格在屏幕上显示,报告日期和价格


  • 但是这种方法有点低级。D3.js是否已经有了一种直接实现这一点的方法:吐出一个
    反转
    数字,它最接近
    数据集中有数据的键?

    根据具体情况,D3.js提供了几个函数:

    1。您在屏幕空间中操作,并希望在表示单个数据对象的可视化最近点上映射当前鼠标位置

    在这种情况下,您可能希望使用

    d3 delaunay是一个快速库,用于计算a的Voronoi图 二维点集。可以使用delaunay.find来标识最接近指针的数据点

    2。如果您在数据域中操作(例如,因为您已经将鼠标位置反转到数据域)

    • 正如所指出的,您可以使用
    d3.bisect查找可以插入给定值的位置 在保持排序顺序的同时将其放入排序数组中。如果值 数组中已存在d3.bisect将找到其位置 有效地

    另见:和

    • d3.js提供的另一个选项是
    阈值比例允许您将域的任意子集映射到范围内的离散值。输入域仍然是连续的,并且根据一组阈值划分为多个片

    其思路如下:

    您可以创建一个d3.scaleThreshold,通过将数据映射到最近的日期,将任何日期(=连续域)映射到给定数据的固定有效日期集。为此,您必须将域指定为n-1个日期的数组,这些日期位于n个有效日期之间。范围是有效日期的数组。 根据您的数据,它可能不如d3.bisect有效

    const data_original=[{date:“2021-03-18”,value:“38.10”},
    {日期:“2021-03-19”,数值:“38.60”},
    {日期:“2021-03-22”,数值:“38.80”},
    ];
    const data_types_converted=data_original.map(d=>({“日期”:新日期(d.date),“值”:+d.value});
    const data\u just\u dates=数据类型\u converted.map(d=>d.date);
    新日期=新日期(“2021-03-17”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    新日期=新日期(“2021-03-18”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    新日期=新日期(“2021-03-19”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    新日期=新日期(“2021-03-20”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    新日期=新日期(“2021-03-21”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    新日期=新日期(“2021-03-22”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    新日期=新日期(“2021-03-23”);
    log(newDate+“->”+getClosestDate(newDate,data_just_dates));
    函数getClosestDate(newDate,validDates){
    常量域=[];
    让正午成为当地人;
    让正午成为UTC;
    有效期。forEach((d,i)=>{
    如果(i

    看一看
    d3.对分
    ,更准确地说是题为“算法:你有两种方法:1)作为@gerardo_