数组插值(或两个)

时间:2009-08-03 11:58:34

标签: java dataset interpolation

我正在寻找一个java库或一些帮助来编写我自己的插值函数。那就是我有两个双打数组,这两个数组可能有不同的大小,但是是有序的。我需要能够估计中间值,并插入以使两个数组的大小相同。事实上,插值中出现的点总数是2个数组大小减1的总和。但是每个数组的范围必须保持不变,因此不需要外推。

例如。 a1 = [1,4,9,16,25,36]和a2 = [6,9,14,30]

结果可能是例如。

a1 = [1,2.25,5,6.25,9,12.25,16,25,36] 和 a2 = [6,6.5625,7.25,9,10.2625,11.25,14,25.25,30]

这些例子是f(x) = x^2 and g(x) = x^2 + 5,但很容易就是任何多项式 - 关键是要能够很好地估计/近似数据集中的函数,以提供足够的插值。这里的x值只是输入数组的索引。在输出中,只有y值很重要。

8 个答案:

答案 0 :(得分:13)

其他答案为您提供线性插值 - 这些并不适用于复杂的非线性数据。 我想要spline fit,(样条插值)我相信。

样条拟合使用来自数据的一组控制点来描述数据的区域,然后在控制点之间应用多项式插值。更多的控制点可以让您更精确地贴合,而不是更适合您。样条曲线比线性拟合更精确,使用速度比一般回归拟合更快,优于高阶多项式,因为它不会在控制点之间做出疯狂的事情。

我不记得我头脑中的名字,但是Java中有一些非常好的拟合库 - 我建议你寻找一个而不是编写自己的函数。


**编辑:可能有用的库:**

**可能有用的理论/代码:**

  • 使用代码link
  • 的样条小程序
  • Arkan样条拟合多边形到bezier样条线
  • Theory样条曲线,以及一些拟合数学。如果图书馆没有,那么更多的数学,更少的代码可能会有所帮助。

答案 1 :(得分:2)

专为ONE Dimension数据阵列设计

import java.util.ArrayList;

public class Interpolator {

public static Float CosineInterpolate(Float y1,Float y2,Float mu)
{
    double mu2;

    mu2 = (1.0f-Math.cos(mu*Math.PI))/2.0f;
    Float f_mu2 = new Float(mu2);
    return(y1*(1.0f-f_mu2)+y2*f_mu2);
}

public static Float LinearInterpolate(Float y1,Float y2,Float mu)
{
    return(y1*(1-mu)+y2*mu);
}


public static Float[] Interpolate(Float[] a, String mode) {

    // Check that have at least the very first and very last values non-null
    if (!(a[0] != null && a[a.length-1] != null)) return null;

    ArrayList<Integer> non_null_idx = new ArrayList<Integer>();
    ArrayList<Integer> steps = new ArrayList<Integer>();

    int step_cnt = 0;
    for (int i=0; i<a.length; i++)
    {
        if (a[i] != null)
        {
            non_null_idx.add(i);
            if (step_cnt != 0) {
                steps.add(step_cnt);
                System.err.println("aDDed step >> " + step_cnt);
            }
            step_cnt = 0;
        }
        else
        {
            step_cnt++;
        }
    }

    Float f_start = null;
    Float f_end = null;
    Float f_step = null;
    Float f_mu = null;

    int i = 0;
    while (i < a.length - 1) // Don't do anything for the very last element (which should never be null)
    {
        if (a[i] != null && non_null_idx.size() > 1 && steps.size() > 0)
        {
            f_start = a[non_null_idx.get(0)];
            f_end = a[non_null_idx.get(1)];
            f_step = new Float(1.0) / new Float(steps.get(0) + 1);
            f_mu = f_step;
            non_null_idx.remove(0);
            steps.remove(0);
        }
        else if (a[i] == null)
        {
            if (mode.equalsIgnoreCase("cosine"))
                a[i] = CosineInterpolate(f_start, f_end, f_mu);
            else
                a[i] = LinearInterpolate(f_start, f_end, f_mu);
            f_mu += f_step;
        }
        i++;
    }

    return a;
}
}

不知道是否有帮助...... 它编码速度非常快,所以如果有人有更好/更好的方式来做同样的事情,感谢您的贡献。

用法:

input : Float[] a = {1.0f, null, null, 2.0f, null, null, null, 15.0f};

call : Interpolator.Interpolate(a, "Linear");

output : 1.0|1.3333333|1.6666667|2.0|5.25|8.5|11.75|15.0

答案 2 :(得分:2)

我知道这是一个陈旧的答案,但它是搜索Java插值时的第一个谷歌搜索。接受的答案提供了一些有用的链接,但必须购买JMSL,JSpline +网站看起来很粗略。

Apache Commons Math具有线性和样条插值的实现,看起来简单,实用且值得信赖。

http://commons.apache.org/proper/commons-math/

答案 3 :(得分:0)

简单的线性插值可以使用类似的方法计算:

Point2D interp1_lin(Point2D p1, Point2D p2, double x) {
 //Pre conditions
assert p1.x<x;
assert x<p2.x;
//Calculate slope from p1 to p2
double m = (p2.x-p1.x)/(p2.y-p1.y);
//Calculate y position of x
double y = (x-p1.x)*m+p1.y;
//create new point
return new Point2D.Double(x,y);
}

这有帮助吗?

答案 4 :(得分:0)

您需要获取与y值对应的x值。否则,没有算法能够确定[1,16,81]对于[1,4,9]是否为x ^ 2或对于[1,2,3]是x ^ 4。你会插入六个值还是没有?

然后,当你给出x值时,你可以使用某种插值(线性,kubic样条,你给它命名)来近似缺失值。

答案 5 :(得分:0)

一维阵列线性插值器的轻量版本:

public static float[] interpolate(float[] data) {
    int startIdx = -1;
    float startValue = 0f;
    float element;
    for (int i = 0; i < data.length - 1; i++) {
        element = data[i];
        if (element != 0f) {
            if (startIdx != -1) {
                doInterpolate(startValue, element, startIdx + 1, i - startIdx - 1, data);
            }
            startValue = element;
            startIdx = i;
        }
    }
    return data;
}

private static void doInterpolate(float start, float end, int startIdx, int count, float[] data) {
    float delta = (end - start) / (count + 1);
    for (int i = startIdx; i < startIdx + count; i++) {
        data[i] = start + delta * (i - startIdx + 1);
    }
}

答案 6 :(得分:0)

对样条拟合和多项式拟合要非常小心。这两者可以提供荒谬的行为,可以破坏数据的许多用途(被认为是数据的代表)。

任何使用数据衍生(斜率)的东西都可以完全脱轨。

你能做的最好的事情是绘制数据,了解它做了什么,然后才适合(线性,多项式,对数 - 对数)回归;一旦你完成了这项工作,你就应该对原始数据进行拟合,并确保你看到合理的协议。跳过这个比较步骤是一个非常糟糕的主意。

某些数据集不会产生拟合多项式,log-log等。如果您的数据点在数据范围内适当分布,则分段插值(线性或多项式等)没有任何问题。要击败死马,如果你使用分段插值避免任何使用分段插值的导数/斜率的东西,因为它会产生不连续性并导致事情表现不佳。

答案 7 :(得分:0)

您可以使用apache commons-math插值functions,例如SplineInterpolator