I have a bunch of points in 2D for which I know the value, and I'd like to fit a cubic spline through them to interpolate some other data around using MATLAB.
My code looks like:
fitobject = fit(x,y,'cubicinterp');
yy=feval(fitobject,xx)
with the following inputs:
Coordinates
x = [...
313 3;
313 5;
313 7;
315 3;
315 5;
317 3;
319 5];
Values
y = [...
28.0779;
28.0186;
11.6220;
16.7640;
23.7139;
-14.7882;
-20.4626];
Interpolation points
xx = [...
313 3;
313 4;
313 5;
313 6;
313 7;
313 8;
313 9;
314 3;
314 5;
314 7;
315 3;
315 4;
315 5;
315 6;
315 7;
316 3;
316 5;
317 3;
317 4;
317 5;
318 3;
319 5;
319 6;
319 7;
320 5];
In my output vector yy, I get several NaN values. To me, the input data look clean (they are all finite values and there's no NaN). I don't get what would cause feval to return NaN when fitting data. Why couldn't it give the best possible fit, even if it is bad? Is there an error in my approach?
I browsed a bit and it seems that the same question had been asked a bunch of times on mathworks forums, but no one gave a clear answer.
Thanks in advance for your help.
It's because an interpolation cannot be used as an extrapolation:
%xx(:,1) xx(:,2) yy
313.0000 3.0000 28.0779
313.0000 4.0000 29.5074
313.0000 5.0000 28.0186
313.0000 6.0000 22.3233
313.0000 7.0000 11.6220
313.0000 8.0000 NaN % xx exceeds bounds of original x interval
313.0000 9.0000 NaN % xx exceeds bounds of original x interval
314.0000 3.0000 24.1239
314.0000 5.0000 27.5130
314.0000 7.0000 NaN % xx exceeds bounds of original x interval
315.0000 3.0000 16.7640
315.0000 4.0000 21.7028
315.0000 5.0000 23.7139
315.0000 6.0000 11.2710
315.0000 7.0000 NaN % xx exceeds bounds of original x interval
316.0000 3.0000 1.4641
316.0000 5.0000 13.9662
317.0000 3.0000 -14.7882
317.0000 4.0000 -5.4876
317.0000 5.0000 2.7781
318.0000 3.0000 NaN % xx exceeds bounds of original x interval
319.0000 5.0000 -20.4626
319.0000 6.0000 NaN % xx exceeds bounds of original x interval
319.0000 7.0000 NaN % xx exceeds bounds of original x interval
320.0000 5.0000 NaN % xx exceeds bounds of original x interval
In other words, you're trying to get data beyond the boundaries of your original surface data (extrapolation), which is usually already quite dangerous, and fit does not even allow you to do it.
It looks like the points which come up as NaN lie outside of the interpolation. You can plot it to take a look.
The code I used to play with this is as follows: (Note that I set the NaNs to -25 just so that they could be plotted)
x = [313 3;
313 5;
313 7;
315 3;
315 5;
317 3;
319 5];
y = [
28.0779
28.0186
11.6220
16.7640
23.7139
-14.7882
-20.4626];
fitobject = fit(x,y,'cubicinterp');
xx = [
313 3
313 4
313 5
313 6
313 7
313 8
313 9
314 3
314 5
314 7
315 3
315 4
315 5
315 6
315 7
316 3
316 5
317 3
317 4
317 5
318 3
319 5
319 6
319 7
320 5];
yy = fitobject(xx);
badindices = isnan(yy);
yy(badindices) = -25;
plot(fitobject, xx, yy, 'Exclude', badindices)
By the way, notice that I'm not using feval, but a direct call to fitobject
Related
i have this code in octave for the runge kutta of the 4th order method but i cant create a graph
dy=#(x,y)-x^2+2*y;
f=#(x)exp(x^2/2);
a=0;
b=2;
y=1;
y0=1;
m=20;
h=(b-a)/m;
k=0;
fprintf('k \t x \t\t y (RK4) \t k1 \t\t k2 \t\t k3 \t\t k4 \n')
fprintf('%d \t %f \t %f \t\n', k,a,y);
for x=a:h:b-h
k1=dy(x,y)*h;
k2=dy((x+h)/2,(y+k1)/2)*h;
k3=dy((x+h)/2,(y+k2)/2)*h;
k4=dy((x+h)/2,(y+k3)/2)*h;
k=k+1;
y=y+dy(x,y)*h;
x=x+h;
fprintf('%d \t %f \t %f \t %f \t %f \t %f \t %f \t \n', k,x,y,k1,k2,k3,k4);
end
fprintf('yn= %f \n',RK4("fedo",a,b,y0,m));
fprintf('Eroarea comisa este de ordinul lui %d \n',h^2);
and i need to create a graph but i dont know what to plot
help?
First, there is an undefined RK4 function in your fprintf statements that doesn't allow us to see the full printed output you desired, but your other code runs, and it looks like the last line is just printing the error estimate. Let's look at the output that does display:
k x y (RK4) k1 k2 k3 k4
0 0.000000 1.000000
1 0.100000 1.200000 0.200000 0.119750 0.111725 0.110923
2 0.200000 1.439000 0.239000 0.142900 0.133290 0.132329
3 0.300000 1.722800 0.283800 0.170030 0.158653 0.157515
4 0.400000 2.058360 0.335560 0.201836 0.188464 0.187126
5 0.500000 2.454032 0.395672 0.239153 0.223501 0.221936
6 0.600000 2.919838 0.465806 0.282984 0.264702 0.262873
7 0.700000 3.467806 0.547968 0.334531 0.313187 0.311053
8 0.800000 4.112367 0.644561 0.395237 0.370304 0.367811
9 0.900000 4.870841 0.758473 0.466834 0.437670 0.434754
10 1.000000 5.764009 0.893168 0.551401 0.517224 0.513806
11 1.100000 6.816811 1.052802 0.651431 0.611294 0.607280
12 1.200000 8.059173 1.242362 0.769917 0.722673 0.717948
13 1.300000 9.527007 1.467835 0.910451 0.854712 0.849139
14 1.400000 11.263409 1.736401 1.077341 1.011435 1.004844
15 1.500000 13.320091 2.056682 1.275759 1.197667 1.189858
16 1.600000 15.759109 2.439018 1.511911 1.419200 1.409929
17 1.700000 18.654931 2.895822 1.793243 1.682985 1.671959
18 1.800000 22.096917 3.441986 2.128692 1.997362 1.984229
19 1.900000 26.192300 4.095383 2.528980 2.372340 2.356676
20 2.000000 31.069760 4.877460 3.006976 2.819928 2.801223
There is a lot here that you could plot. But there's a small problem here, which is that all of that data is not saved in any variables. It's just printed to the screen and then overwritten on the next iteration of your RK loop. For example, after the program runs your workspace contains the following variables:
>> whos
Variables visible from the current scope:
variables in scope: top scope
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x1 8 double
b 1x1 8 double
dy 1x1 0 function_handle
f 1x1 0 function_handle
h 1x1 8 double
k 1x1 8 double
k1 1x1 8 double
k2 1x1 8 double
k3 1x1 8 double
k4 1x1 8 double
m 1x1 8 double
x 1x1 8 double
y 1x1 8 double
y0 1x1 8 double
>> k1
k1 = 4.8775
where all of the variables only retain the last value, k1 shown as an example.
If you want to plot the information, you need to retain the information to plot. if I manually copied/pasted your data into the terminal to define a data variable (ignoring the first partial line):
>> data = [1 0.100000 1.200000 0.200000 0.119750 0.111725 0.110923
2 0.200000 1.439000 0.239000 0.142900 0.133290 0.132329
3 0.300000 1.722800 0.283800 0.170030 0.158653 0.157515
4 0.400000 2.058360 0.335560 0.201836 0.188464 0.187126
5 0.500000 2.454032 0.395672 0.239153 0.223501 0.221936
6 0.600000 2.919838 0.465806 0.282984 0.264702 0.262873
7 0.700000 3.467806 0.547968 0.334531 0.313187 0.311053
8 0.800000 4.112367 0.644561 0.395237 0.370304 0.367811
9 0.900000 4.870841 0.758473 0.466834 0.437670 0.434754
10 1.000000 5.764009 0.893168 0.551401 0.517224 0.513806
11 1.100000 6.816811 1.052802 0.651431 0.611294 0.607280
12 1.200000 8.059173 1.242362 0.769917 0.722673 0.717948
13 1.300000 9.527007 1.467835 0.910451 0.854712 0.849139
14 1.400000 11.263409 1.736401 1.077341 1.011435 1.004844
15 1.500000 13.320091 2.056682 1.275759 1.197667 1.189858
16 1.600000 15.759109 2.439018 1.511911 1.419200 1.409929
17 1.700000 18.654931 2.895822 1.793243 1.682985 1.671959
18 1.800000 22.096917 3.441986 2.128692 1.997362 1.984229
19 1.900000 26.192300 4.095383 2.528980 2.372340 2.356676
20 2.000000 31.069760 4.877460 3.006976 2.819928 2.801223];
Then I can plot all sorts of things, like y vs k, or y vs x, etc:
plot (data(:,1), data(:,3)); title ("y vs k");
figure
plot (data(:,2), data(:,3)); title ("y vs x");
So the big question is how to retain your data so you aren't reliant on copy/paste.
Octave and Matlab variables are arrays. In your case, the variables you store your data in are single element, 1x1 arrays, and you overwrite them every iteration. An alternative approach is to use a vector for each variable (just as your printed output appears), and to store values from each iteration in a different vector location, indexed by k.
I notice that some of your variables you print are actually not the variables you use for each step. E.g., for k = 1, you print x = 0.1 but all of those values are calculated with k= 0 and x = 0. You then increment x and k right before printing. So some of those details might need to be tweaked to get what you want to match with what follows:
Since you're using x to define your steps, you probably want to expand that to an array first:
>> x=[a:h:b-h];
>> x'
x =
0
0.1000
0.2000
0.3000
0.4000
0.5000
0.6000
0.7000
0.8000
0.9000
1.0000
1.1000
1.2000
1.3000
1.4000
1.5000
1.6000
1.7000
1.8000
1.9000
(Note the vector is normally a row vector, I used a ' (transpose operator) to makes it display as a column vector here. I do the same at the end for storing results.)
The following rewritten RK loop produces an output much like your previous output:
x=[a:h:b];
for k = 1:length(x)-1
k1(k+1) = dy(x(k),y(k))*h;
k2(k+1) = dy((x(k)+h)/2,(y(k)+k1(k+1))/2)*h;
k3(k+1) = dy((x(k)+h)/2,(y(k)+k2(k+1))/2)*h;
k4(k+1) = dy((x(k)+h)/2,(y(k)+k3(k+1))/2)*h;
y(k+1) = y(k) + dy(x(k),y(k))*h;
end
data = [x',y',k1',k2',k3',k4']
data =
0 1.0000 0 0 0 0
0.1000 1.2000 0.2000 0.1198 0.1117 0.1109
0.2000 1.4390 0.2390 0.1429 0.1333 0.1323
0.3000 1.7228 0.2838 0.1700 0.1587 0.1575
0.4000 2.0584 0.3356 0.2018 0.1885 0.1871
0.5000 2.4540 0.3957 0.2392 0.2235 0.2219
0.6000 2.9198 0.4658 0.2830 0.2647 0.2629
0.7000 3.4678 0.5480 0.3345 0.3132 0.3111
0.8000 4.1124 0.6446 0.3952 0.3703 0.3678
0.9000 4.8708 0.7585 0.4668 0.4377 0.4348
1.0000 5.7640 0.8932 0.5514 0.5172 0.5138
1.1000 6.8168 1.0528 0.6514 0.6113 0.6073
1.2000 8.0592 1.2424 0.7699 0.7227 0.7179
1.3000 9.5270 1.4678 0.9105 0.8547 0.8491
1.4000 11.2634 1.7364 1.0773 1.0114 1.0048
1.5000 13.3201 2.0567 1.2758 1.1977 1.1899
1.6000 15.7591 2.4390 1.5119 1.4192 1.4099
1.7000 18.6549 2.8958 1.7932 1.6830 1.6720
1.8000 22.0969 3.4420 2.1287 1.9974 1.9842
1.9000 26.1923 4.0954 2.5290 2.3723 2.3567
2.0000 31.0698 4.8775 3.0070 2.8199 2.8012
(Also note octave and matlab start indexing at 1 not zero, hence all the k+1's)
Now that all of the data is stored and retained in the individual variable vectors or in the data array, you can make any plots you want. Recommend you check out the Octave manual section on plotting.
I am trying to use fmincon to optimize x such that R*x is minimized while x can be values between 0 and 1.5 and the sum(x) = 3
R = transpose([6 6 6 6 6 6 6 9 9 9 9 13 13 13 13 9 9 9 9 6 6 6 6 6]);
x0 = zeros(24,1);
f='0';
for j=1:24
s='%d*x(%d)';
s=sprintf(s,R(j),j);
g='%s+%s';
f=sprintf(g,f,s);
end
A = ones(2,24);
A(2,:) = -1;
b = [1.5; 0]; % Want x's to be between 0 and 1.5
Aeq = ones(1,24);
beq = [3];
%Bounds
lb = zeros(24,1);
ub = ones(24,1);
x = fmincon(f, x0, A, b,Aeq, beq,lb,ub);
I want the sum of x to equal 3 (attempted to show this with equivalency matrices Aeq and beq). The following error was shown when I run the code:
converged to an infeasible point
It should be noted that this code shows that sum(x) = 2.25 instead of sum(x) = 3
First, your function definition can be shortened to:
R = [6 6 6 6 6 6 6 9 9 9 9 13 13 13 13 9 9 9 9 6 6 6 6 6];
f = #(x)R*x;
Second, your initial point x0 does not satisfy your constraints, so let's change it to:
x0 = zeros(24,1)+3/24;
so that the sum of x is equal to 3.
Next, since you have a constant upper and lower bounds on x, you don't need to use A and b matrices, so we get rid of them and replace them with empty matrices []. We will rely only on lb and ub instead:
lb = zeros(24,1);
ub = 1.5*ones(24,1);
Finally, we start fmincon by using
x = fmincon(f, x0,[],[],Aeq, beq,lb,ub)
Optimization completed because the objective function is non-decreasing in
feasible directions, to within the default value of the optimality tolerance,
and constraints are satisfied to within the default value of the constraint tolerance.
<stopping criteria details>
x =
0.2500
0.2500
0.2500
0.2500
0.2500
0.2500
0.2500
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.0000
0.2500
0.2500
0.2500
0.2500
0.2500
I'm trying to remove the trailing zeros, after the decimal point, from the first row of the following matrix A.
A1 = [130: -20: 10]
A2 = [1: 11/6: 12]
A3 = [1/2: 1/4: 2]*pi
A = [A1; A2; A3]
Which is displayed as:
A = 130.0000 110.0000 90.0000 70.0000 50.0000 30.0000 10.0000
1.0000 2.8333 4.6667 6.5000 8.3333 10.1667 12.0000
1.5708 2.3562 3.1416 3.9270 4.7124 5.4978 6.2832
The final matrix has to be like this one:
How can I do this?
A1 = [130: -20: 10];
A2 = [1: 11/6: 12];
A3 = [1/2: 1/4: 2]*pi;
format shortG % Where the magic happens
A = [A1; A2; A3]
A =
130 110 90 70 50 30 10
1 2.8333 4.6667 6.5 8.3333 10.167 12
1.5708 2.3562 3.1416 3.927 4.7124 5.4978 6.2832
Just use format shortG. The zeros are there technically only as a numerical accuracy-thing. Check the documentation on format for all display styles.
We're working on a MATLAB code to rank stocks. We do not have a full dataset and therefore have to cope with some NaNs. However, in the code we use for sorting, the NaNs are ranked the highest. Our intention is to exclude the NaNs from the ranking. How to do this?
Please consider an example with Y and stockkid below
Y = [1.2 1.3 NaN 0.9 0.95 NaN 0.8 0.7];
stockid = [801 802 803 804 805 806 807 808];
[totalmonths,totalstocks] = size(Y);
nbrstocks = totalstocks - sum(isnan(Y));
[B,I] = sort(Y,'descend');
ncandidates = 4;
idwinner(1:ncandidates) = stockid(I(1:ncandidates));
Running the program results in:
Y =
1.2000 1.3000 NaN 0.9000 0.9500 NaN 0.8000 0.7000
idwinner =
803 806 802 801
So, 803 corresponds to NaN, 806 to NaN, 802 to 1.3 etc.
The result we're aiming for should be like this:
Y =
1.2000 1.3000 NaN 0.9000 0.9500 NaN 0.8000 0.7000
idwinner =
802 801 805 804
So, how can we exclude the NaNs from the ranking?
Use
Y(isnan(Y)) = -inf;
before calling sort. That will change NaN values into -inf, and thus those values will be the lowest.
Alternatively, if you don't want to change any value in Y, you can use an intermediate index as follows:
Y = [1.2 1.3 NaN 0.9 0.95 NaN 0.8 0.7];
stockid = [801 802 803 804 805 806 807 808];
ind = find(~isnan(Y)); %/ intermediate index that tells which elements are numbers
[B,I] = sort(Y(ind),'descend');
ncandidates = 4;
idwinner(1:ncandidates) = stockid(ind(I(1:ncandidates))); %// apply intermediate index
After your sort statement, add the line: I = I(~isnan(B));, which will remove the indices associated with NaNs before you select them from stockids
I = I(~isnan(B));
Works best since we then do not overwrite the NaNs as is the case with using
Y(isnan(Y)) = -inf;
Since we later on also have to determine the loser portfolios from the stocks with the lowest returs. This does not work well with the last code because all the NaNs have the lowest returns instead of the stocks with actual data.
Let say I have a 6x5 matrix (my actual data is way bigger)
A B C D E
1 5 7 2 3
2 1 9 8 5
3 1 2 3 1
4 1 3 4 2
5 2 9 0 1
6 5 3 4 3
I have to make a plot with A on the x-axis and B,C,D on the y-axis. If I want to reduce the data points by half (by averaging each adjacent pair of data points), how do I do it? What if I want to decrease the points even further by averaging every five (or n) points?
I looked at the MATLAB help document but I'm still confused
I got what I needed, thanks for the input guys, it really helped
There you go:
M = [1 5 7 2 3
2 1 9 8 5
3 1 2 3 1
4 1 3 4 2
5 2 9 0 1
6 5 3 4 3]; % data
>>result = (M(1:2:end-1,:) + M(2:2:end,:))/2;
result =
1.5000 3.0000 8.0000 5.0000 4.0000
3.5000 1.0000 2.5000 3.5000 1.5000
5.5000 3.5000 6.0000 2.0000 2.0000
An even number of rows scenario is straightforward, using mean to do the work:
>> M = magic(4)
M =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> reshape(mean(reshape(M,2,[]),1),[],size(M,2))
ans =
10.5000 6.5000 6.5000 10.5000
6.5000 10.5000 10.5000 6.5000
For the odd number of rows scenario, let's say you want to retain the last row. Here's a general even/odd solution:
>> M = magic(5) % 5 rows!
M =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
>> Mp = [M; repmat(M(end,:),mod(size(M,1),2),1)]; % replicate last row if odd
>> Mthin = reshape(mean(reshape(Mp,2,[]),1),[],size(Mp,2))
Mthin =
20.0000 14.5000 4.0000 11.0000 15.5000
7.0000 9.0000 16.0000 20.5000 12.5000
11.0000 18.0000 25.0000 2.0000 9.0000
Alternatively, if you want to throw away the last row when encountered with an odd number of rows:
>> Mp = M(1:end-mod(size(M,1),2),:);
>> Mthin = reshape(mean(reshape(Mp,2,[]),1),[],size(Mp,2))
Mthin =
20.0000 14.5000 4.0000 11.0000 15.5000
7.0000 9.0000 16.0000 20.5000 12.5000
Now for averaging n points, retaining the average of the mod(size(M,1),n) last rows:
n = 5;
M = rand(972,5); % or whatever
p = mod(size(M,1),n);
r = repmat(mean(M(end-p+1:end,:),1),(p>0)*(n-p),1);
Mp = [M; r];
Mthin = reshape(mean(reshape(Mp,n,[]),1),[],size(Mp,2));
And for throwing out the last mod(size(M,1),n) rows:
Mp = M(1:end-mod(size(M,1),n),:);
Mthin = reshape(mean(reshape(Mp,n,[]),1),[],size(Mp,2));
>>> A= magic(5) %some "random" data
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
>>> B=(A(1:2:end-1,:)+A(2:2:end,:))/2
B =
20.0000 14.5000 4.0000 11.0000 15.5000
7.0000 9.0000 16.0000 20.5000 12.5000
Takes average of each pair of rows, ignores the last row if row count is not even.
And some general solution:
%input data data
X=randi(30,30,5)
step=7
%extend matrix, until size matches step (could be done faster using repmat)
while(mod(size(X,1),step)~=0)
X(end+1,:)=X(end,:)
end
%Split data into segments of size "step"
C=mat2cell(X,repmat(step,floor(size(X,1)/step),1),size(X,2))
%Average over each segment:
AVG=cell2mat(cellfun(#(x)(mean(x,1)),C,'UniformOutput',false))