'The grid vectors must contain unique points.' error with Interp1

I have a code that I've been working on and currently I'm facing a bit of an issue:
table = temp.data %temp is the command where I import the data
x = table(:,2)
y = table(:,3)
z = table(:,1)
[xmax,ind] = max(x)
range = 0.1:0.05:xmax
A = interp1(x(1:ind),y(1:ind),range)
B = interp1(x(1:ind),z(1:ind),range)
In my code, 'x' 'y' and 'z' are two sets of data that come from the file 'data'attached to this. However, every time I try to run it, it always throws this error: Error using griddedInterpolant The grid vectors must contain unique points. Could someone help me? I don't know why is it appearing. I tried with small values and it works but, somehow, with this, it doesn't work.

 Accepted Answer

One approach:
x = table(:,2);
x = x + (0:size(D,1)-1)'*1E-14;
The rest of your code is unchanged.

6 Comments

This answer is incorrect. x is far more seriously non-monotonic than the tiny tweak Star has suggested will correct. In fact, it will cause interp1 to produce a very different curve, because interp1 will do a sort on what it sees as x.

The curve that Star's method would have you produce is:

The issue is that if x is not an increasing sequence, interp1 actually does a sort on x. That causes the curve it would produce to now oscillate extremely rapidly, as you see in the plot. So while interp1 would not fail with an error, it will produce garbage.

It depends on what you want to do. In my answer, I show that you can interpolate that data, if you use z as the independent variable. However, if you are trying to produce points along the curve (x,y) that are equally spaced in x, then I'm not sure what your intent is there, when that relationship is not a single valued function of x. One idea is to use a tool I posted on the file exchange, that can produce points at a uniformly spaced distance along the curve (x,y).
I see, in the end I had to use the values of x from the first to the point where it starts to descend but thank you for the answer!
But what you need to understand is that the method Star gave you does not interpolate the curve as you have it. It ONLY avoids generating an explicit error!
Interp1 sorts the data on x. But that sort completely changes the shape of the curve from what you had.

Sign in to comment.

More Answers (2)

Lets actually plot the data. ALWAYS plot your data. Look at it. Think about what it means.
plot(x,y,'.')
So y is not a single valued function of x. Interp1 needs a relationship where for any specific point on the x axis, there must be a unique value of y. However, between x=1.08 and x=1.16, the curve doubles back on itself. So in that interval, there are actually THREE values of y, three possible values that interp1 could possibly predict.
This is caused because x is not increasing in a monotonic fashion.
Similarly, z is also not a single valued function of x, as we see here:
plot(x,z,'.')
Interp1 is simply not designed to solve this class of problem, at least as you have presented it to interp1.
In fact, the independent variable seems to be z, the first column of your table. z is a nice monotonic sequence. In reality, your problem is of the form x(z) and y(z), where z moves smoothly forward. If we try to plot the data in a logical way that interp1 would have no problem interpolating:
plot(z,x)
plot(z,y)
So, we can plot those curves in a way that makes sense, as they seem to have been produced. What you cannot now do is to use interp1 to interpolate y as a function of x. x is not such that you can use interp1 here.
That does not mean you cannot solve the problem. The simplest solution is to use z as the independent variable, as I showed. People think that a tool like interp1 can interpolate any sequence of (x,y) pairs, well, that it should be able to do so.
Perhaps at the very least, interp1 should generate a warning message, rather than attempting to sort the vector x.

1 Comment

As a possible solution, perhaps what you are looking to find is something that can interpolate a non-functional relationship.

If so, then a good choice may be my interparc , posted on the file exchange. It works in terms of distance along the curve itself.

xy =interparc(50,x,y);
plot(x,y,'b-',xy(:,1),xy(:,2),'ro')
grid on
xz =interparc(50,x,z);
plot(x,z,'b-',xz(:,1),xz(:,2),'ro')
grid on

Interparc work in terms of arclength along the curve. So it has no problems with a relationship that is not a true functional one. As far as it is concerned, a curve is just a general path through the (x,y) plane.

Be careful in how you interpret the plots though. While it looks like the points in these plots are not equally spaced in terms of distance along the curve, the failure arises because x, y, and z seem to have totally different scalings. For example, x ranges from roughly 0 to almost 2, yet y is scaled to lie roughly between 0 and 0.09.

You can download interparc from the file exchange, here:

https://www.mathworks.com/matlabcentral/fileexchange/34874-interparc

Sign in to comment.

The first parameter you pass to interp1() needs to be the independent variable. In your data, the independent variable appears to be column 1, which you have assigned to z. The second column, which you assign to x, increases for a time, decreases a little, and then increases again, and so is not strictly monotonic. The first parameter you pass to interp1 needs to be strictly monotonic.
Your x data has two data points that are both 1.1393, one at index 95 and the other at index 132.

Categories

Find more on Interpolation in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!