ChartJS 图表- Y轴显示值和步长计算

8ulbf1ek  于 2023-08-05  发布在  Chart.js
关注(0)|答案(1)|浏览(231)

所以我有一个配对列表:[(0,15.0),(1,17.0),(2,20.0),(3,28.5),(4,29),(5,32.0),(6,33.5),(7,33.6)]
我想创建一个散点图,其中第一个数字将是X值(和X轴标签),第二个数字将是Y轴值。
我的参考点是MS Excel,在那里我可以选择2列和一些行,我可以插入一个散点图。在MS Excel中,Y轴标签被很好地计算出来,所以在我的示例数据集中,Y轴标签将是0,5,10,15,20,25,30,35。
我的问题是我的数据集可以有各种Y值(包括负数)从最低的Double值可能到最高的Double值可能。
我无法找到如何创建这个人类可读的Y轴标签计算的逻辑,所以我会得到像10,20,30,40,50 10,100,1000,10000 10,50,100,150 0,200,400,600,800,0,300,600,900等标签
我希望Y轴标签计数在一定程度上是动态的,因此如果数据范围很大,我最终不会有超过8个标签,而如果数据范围很小,我仍然会看到至少5个而不仅仅是2个。此外,次要要求是例如如果Y轴标签将是0.0、0.5、1.0、1.5、2.0、2.5 -我需要能够改变分数数字计数,因此它可能是0.00、0.50、1.00、1.50 -或者如果我设置零分数数字,则不仅标签将改变,而且y轴步长也将改变,因此它们将是0、1、2、3、4、5等。
现在我正在寻找任何编程语言的解决方案。最好是Chart.js,React,Kotlin,Swift,但基本上什么都行,我只需要一些我可以用我所需的语言实现的方向/逻辑。我不想依赖于Chart.js或其他语言不存在的python库。
谢谢你,谢谢
这是我在Kotlin中尝试的,在某些情况下,我最终有15个甚至20个标签,我想确保最低和最高的Y轴标签总是低于和高于数据集中最低和最高的y值:

private fun calculateStepSize(range: Double, preferredLabelCount: Int): Double {
    // calculate raw step
    val rawStep = range / preferredLabelCount

    // calculate magnitude of the step
    val magnitude = floor(log10(rawStep)).toInt()

    // calculate most significant digit of the new step
    var mostSignificantDigit = (rawStep / 10.0.pow(magnitude.toDouble())).roundToInt()

    // promote most significant digit to 1, 2, or 5
    mostSignificantDigit = if (mostSignificantDigit > 5) {
        10
    } else if (mostSignificantDigit > 2) {
        5
    } else {
        1
    } // 10 20 30 ... 10 50 100 150... 10 100 1000...

    // generate new step
    return mostSignificantDigit * 10.0.pow(magnitude.toDouble())
}

// start at label count 7, that means on the y Axis, there will be 7 values shown
var yAxisLabelCount = 7
var yAxisRange = maxYValue - minYValue
var yAxisValueStep = calculateStepSize(yAxisRange, yAxisLabelCount - 1)

var yAxisRoundedMin = floor(minYValue / yAxisValueStep) * yAxisValueStep

var yAxisMax = yAxisRoundedMin + (yAxisLabelCount - 1) * yAxisValueStep

while (yAxisMax < maxYValue) {
    yAxisLabelCount++
    yAxisRange = maxYValue - minYValue
    yAxisValueStep = calculateStepSize(yAxisRange, yAxisLabelCount - 1)
    yAxisRoundedMin = floor(minYValue / yAxisValueStep) * yAxisValueStep
    yAxisMax = yAxisRoundedMin + (yAxisLabelCount - 1) * yAxisValueStep
}

字符串

zbdgwd5y

zbdgwd5y1#

总体思路:

- Specify how many ticks you want on your axis ( tick_count )
- Find the range of the data ( max - min )
- tick_increment = range / tick_count, rounded down to integer
- tick_value = min
- LOOP
    tick_value += tick_increment

字符串
这看起来很直接。诀窍在于处理特殊情况所需的所有额外代码。
下面是一些C++代码,可以处理其中的一些问题

std::vector< double > tickValues(
    double mn, double mx )
{
    std::vector< double > vl;
    double range = mx - mn;
    if( range < minDataRange )
    {
        // plot is single valued
        // display just one tick
        vl.push_back( mn );
        return vl;
    }
    double inc = range / 4;
    double tick;
    if( inc > 1 )
    {
        inc = ( int ) inc;
        tick  = ( int ) mn;
    }
    else
    {
        tick = mn;
    }
    while( true )
    {
        double v = tick;
        if( v > 100)
            v = ((int) v / 100 ) * 100;
        else if( v > 10 )
            v = ((int) v / 10 ) * 10;
        vl.push_back( v );
        tick += inc;
        if( tick >= mx )
            break;
    }
    vl.push_back( mx );
    return vl;
}


完整2D出图类别https://github.com/JamesBremner/windex/blob/master/include/plot2d.h的程式码
建议:准备好处理任意数据集的功能齐全、功能强大的二维绘图仪需要大量的代码,因此,与其自己编写代码,最好不要重新发明轮子并找到合适的库或应用程序。

相关问题