Search code examples
arraysmatlabstatisticsgraphinginterpolation

Matlab Interpolating 1D Scattered Data


I have some data that is organized simply as 2D (x,y) coordinates. I have a large amount of this data and while the data for the X axis has the same range for all the points, it doesn't use the same exact X points between data sets. I would like to interpolate each set of data and then grab the same X points for each data set. Whenever I use Matlab to try and interpolate the data I run into problems.

So my data looks like:

x = [0 1 2 3 4 5 6 7]
y = [2.2 3.7 3.9 4.1 4.2 8.9 9.1 9.3]
xq = [0.5 0.75 2 2.25]

where x and y are my recorded data values and xq are the new x points that I would like to get from the interpolated data.

typically I use the interp1 command as such:

f = interp1(x,y,xq);

unfortunately this command produces the error: "The grid vectors are not strictly monotonic increasing." This happens if I use griddata or related commands. I understand that this is because I have data that isn't from a function and therefore I need a technique that deals with scattered data. So I have attempted to use scatteredInterpolant but it appears that this function appears to be not suited for this type of data, as it needs x, y, and a v (value) matrix, which is more dimensions than I have.

I am at a loss on how to continue, advice, and suggestions would be greatly appreciated.


Solution

  • I'm going to take a stab at this, although you really do need to provide a real working example of your code and an actual version of the input data that throws the error. The code and data you posted work just fine:

    f =
    
             2.95        3.325          3.9         3.95
    

    The error you're getting implies that your actual x vector is not sorted as it is in your example here, or else it contains duplicate values (i.e. x = [0 1 1 2 3];). You can test for the first case using the issorted(x) command and for the second with any(diff(x) == 0).

    The first case is easy to fix:

    [x,ix] = sort(x);
    y = y(ix);
    xq = sort(xq);
    yq = interp1(x,y,xq);
    

    There are a couple ways to deal with the second case, depending on your application. You can either search for the duplicates and shift them by ±eps, average them together, or discard them.

    Without data that duplicates your error, though, we're all just kind of guessing.

    Update:

    Looking at the data you posted (and for posterity's sake you should edit directly into your question), you have both problems. Your data isn't sorted and there are duplicates. Sorting, as I said, is easy. After sorting as above, this is what I've done in the past to take care of duplicate entries:

    xu = unique(x);
    yu = y;
    duplicated = xu(histc(x,xu) > 1); % find the duplicated entries
    discardIndex = [];
    for k = 1:length(duplicated);
        dupIndex = sort(find(x == duplicated(k))); % look for duplicated entries
        keepIndex = dupIndex(1); % keep only the first one
        discardIndex = [discardIndex dupIndex(2:end)]; % add the rest to a list
        yu(keepIndex) = mean(y(:,dupIndex)); % take the mean of the y values at the duplicated x values
    end
    yu(discardIndex) = []; % after all is said and done, delete the duplicated entries.
    

    I wrote that a long time ago and is almost certainly not the most efficient way to do it, but it will work.