Correlation of curves using Matlab - matlab

I have two sets of data. Each of them is a matrix and they have two columns, first column represents index x and second represents y. I want to see how similar are the curves of these datasets. In other words I need to have the correlation of these two curves represented by two matrices.
Thanks for help.

You might be looking for the corr2 function which calculates the correlation coefficient for each corresponding values in your matrices:
CorrMatrix = corr2(A,B)
plot(x,CorrMatrix);
Is that what you meant? If not please don't hesitate to ask for more details.
For matrices of unequal size I think you only have these options:
If you have the Signal Processing Toolbox you can use the cross-correlation function xcorr2, otherwise you can do the following:
1)either you calculate the correlation of you data where you use a part of the larger matrix so that the number of elements are similar: (the values I use are really dummy values sorry.)
clear
clc
% Create dummy matrices of unequal sizes
x =1:10;
x2 = 1:6;
A(:,1) = x;
A(:,2) = sin(x);
B(:,1) = x2;
B(:,2) = cos(x2);
A,B
C = corr2(A(1:6,:),B)
A =
1.0000 0.8415
2.0000 0.9093
3.0000 0.1411
4.0000 -0.7568
5.0000 -0.9589
6.0000 -0.2794
7.0000 0.6570
8.0000 0.9894
9.0000 0.4121
10.0000 -0.5440
B =
1.0000 0.5403
2.0000 -0.4161
3.0000 -0.9900
4.0000 -0.6536
5.0000 0.2837
6.0000 0.9602
C =
0.9463
or 2)
After some googling I saw that a similar question was posted here, in which it said that you can play around with Fourier transforms to get the correlation:
Cross-correlation in matlab without using the inbuilt function?

Related

corrcoef function of matlab works wrongly

I used corrcoef function of matlab to find correlation between two images.
First I use Correlation between all corresponding points
A_2=double(imread('prometmonew1.tif'));
B_2=double(imread('lai5min1bas1.tif'));
R = corrcoef(A_2(:),B_2(:))
The result is
R =
1.0000 1.0000
1.0000 1.0000
but when I remove some parts of the images (backgrounds) and then I use this function again the correlation is different(the values of backgrounds are negative), how is it possible? whats wrong?
V=find(A_2>=0);
A=A_2(V);
V_1=find(B_2>=0);
B=B_2(V_1);
R = corrcoef(A,B)
R =
1.0000 0.3275
0.3275 1.0000
Thanks in advance

Interpolation for corresponding constant section in matlab

How to do linear interpolation for a vector corresponding to a constant section? For example we have a matrix of two column as follow.
Matrix =
125.2985 5.7057
125.2991 5.7098
125.2997 5.6880
125.3004 5.6739
125.3010 5.7140
125.3016 6.0141
125.3022 6.3620
125.3029 6.4793
125.3041 6.4665
125.3047 6.4646
125.3053 6.4844
125.3060 6.4743
125.3066 6.4865
125.3072 6.4878
125.3078 6.4975
125.3085 6.4952
125.3091 6.4958
125.3128 6.5867
125.3134 7.0733
125.3141 7.3427
125.3147 7.3238
125.3153 7.3093
125.3159 7.3188
125.3166 7.3436
A second matrix is as 'C'.
C =
125.2985 2.0000
125.3004 3.0000
125.3053 5.0000
125.3085 4.0000
125.3147 6.0000
125.3166 7.0000
Now I need to do interpolation of 'C(:,2)' values for 'Matrix(:,1)'. The out put result of linear interpolation is as follow
Cinter=interp1(C(:,1),C(:,2),Matrix(:,1),'linear')
Cinter =
2.0000
2.3158
2.6316
3.0000
3.2449
3.4898
3.7347
4.0204
4.5102
4.7551
5.0000
4.7813
4.5937
4.4063
4.2187
4.0000
4.1935
5.3871
5.5806
5.8065
6.0000
6.3158
6.6316
7.0000
But I want to do interpolation only for those data points where 'Matrix(:,2)' is fairly stable. The rest should be as NaN in the interpolated vector. The required output should be as follow instead of 'Cinter'. How to achieve this?
output1=
2.0000
2.3158
2.6316
3.0000
NaN
NaN
NaN
NaN
NaN
NaN
5.0000
4.7813
4.5937
4.4063
4.2187
4.0000
NaN
NaN
NaN
NaN
6.0000
6.3158
6.6316
7.0000
This also can be taken a step further to achieve a second desired output. Based on first 'output1' data points (NaN) at constant 'Matrix(:,2)' can be replaced by nearby 'C(:,2) value'. The second output would be as follow and how to get this?
output2=
2.0000
2.3158
2.6316
3.0000
3.0000
NaN
NaN
5.0000
5.0000
5.0000
5.0000
4.7813
4.5937
4.4063
4.2187
4.0000
4.0000
4.0000
NaN
6.0000
6.0000
6.3158
6.6316
7.0000
Thank you very much.
Best regards
To find stable regions, you could estimate derivatives (presumably first and/or second depending on what you mean by "stable") and then select only those within some range; e.g. using gradient for the first derivative:
stable = abs(gradient(Matrix(:,2),Matrix(:,1))) < 50;
Cinter = NaN(size(Matrix,1),1);
Cinter(stable) = interp1(C(:,1),C(:,2),Matrix(stable,1),'linear')
If you want to keep every point that has low slope on the left or on the right, you could try something like:
grad = diff(Matrix(:,2)) ./ diff(Matrix(:,1));
leftgrad = [0; grad];
rightgrad = [grad; 0];
stable2 = abs(leftgrad) < 50 | abs(rightgrad) < 50;
You could then use stable2 instead of stable above; if you insist on picking the value at the closest point (rather than the interpolated points), why not do:
boundary = stable2 & not(stable);
Cinter(boundary) = interp1(C(:,1),C(:,2),Matrix(boundary,1),'nearest')

Am I facing floating point issue?

Let's say f(x) = (4x^2-9)/(2x-3). The function f(x) is undefined at x=3/2. Note that the function can be factored to yield f(x)=2x+3 but let's examine the first equation. In the following script when x=1.5, the function f(x=1.5)=4.0
clear all
clc
x = 0:0.3:2;
for i = 1:length(x)
if x(i) == 1.5 % this line for some reasons is ignored.
y(i) = 6;
else
y(i) = (4*x(i)^2-9)/(2*x(i)-3);
end
end
x
y
The output of the preceding script is
x = 0 0.3000 0.6000 0.9000 1.2000 1.5000 1.8000
y = 3.0000 3.6000 4.2000 4.8000 5.4000 4.0000 6.6000
Why y=4.0000 when x=1.5000? Now let's run the code without for-loop,
clear all
clc
x = 0:0.3:2
y = (4*x.^2-9)/(2*x-3)
The result of the above code is
x = 0 0.3000 0.6000 0.9000 1.2000 1.5000 1.8000
y = 3.6000
There is only one value for f(x). Can any one explain what is going on?
As for your first question, yes, you are running into a floating point precision error. You can check this by checking the difference between the x value that it's supposed to be a 1.5 and a 1.5.
x(6)-1.5
%ans=
% -2.2204e-16
Specifically in your case it comes from using 0.3 to construct the vector x since that value cannot be precisely saved into binary, see here for a deeper explanation
Any of the following should solve your problem
x=0:3:20; %Create the vector based on values that can be represented
x=x/10;
x=[0, 0.3, 0.6, 0.9, 1.2, 1.5, 1.8]; %Directly input the values
abs(x(i)-1.5) < tol %Instead of directly comparing values, compare the difference to a determined tolerance (very small compared to the values at hand)
As for your second question #Phill already gave you the answer, you are using / matrix division, and you want ./ element wise division.
When I run your first example with the for loop in Octave, I do not see a problem with the x=1.5 if statement being ignored. Perhaps this is a subtle difference between Matlab and Octave for this although I would be surprised.
For the array notation second example
clear all
clc
x = 0:0.3:2
y = (4*x.^2-9)/(2*x-3)
You have chosen the matrix division operator / instead of the element by element division operator ./

How I ignore the elements NaN in matrix for polynomial adjustment and use the "a" and "b" of the equation of polyfit?

I have a matrix with size 9x27. Each column correspond a simple variable, I need to plot a variable one with example:
m = [7.0000 10.0307
8.0000 5.4601
9.0000 4.2331
10.0000 2.8221
11.0000 4.0491
12.0000 5.2147
13.0000 7.1779
14.0000 13.0675
15.0000 NaN...]
plot(m(:,1),m(:,2))
Posteriorly, I need to adjust of polynomial(2) "quadratic". However, my numbers of the equation not out for me.
a = polyfit(m(:,1),m(:,2),2)
a =
NaN NaN NaN
I would like to delete the NaN elements for so that numbers of the equation can be used after.
I need to find the minimal value for the adjust polynomial. The derivative zero. "b/2*a".
I hope have a been clear!
I thank everyone's attention.
Assuming the presence of a NaN means the rest of the row is useless, it's probably best to simply filter out those rows:
validrows = ~any(isnan(m), 2);
a = polyfit(m(validrows,1), m(validrows,2), 2)

How do I create a stacked bar plot in Matlab that fix certain values to specific colors?

I'm trying to make a stacked bar plot that should show how different types of rock are varying with depth. I have generated some fictive lithology series based on some real data and want to present them in a readable way. So now I have this matrix A:
A =
2.0000 65.0000
1.0000 19.5000
2.0000 0.5000
4.0000 1.5000
2.0000 58.0000
4.0000 2.0000
2.0000 22.5000
3.0000 7.0000
2.0000 14.5000
3.0000 12.5000
4.0000 2.5000
2.0000 31.5000
1.0000 20.0000
2.0000 20.0000
1.0000 15.5000
2.0000 66.0000
4.0000 0.5000
2.0000 2.5000
3.0000 8.0000
2.0000 61.0000
1.0000 17.5000
2.0000 8.0000
5.0000 19.5000
3.0000 24.5000
where the first column represents the different rock types and the second column the thickness (in meters) of each lithology layer. And now I want to plot this looking like a core-data log. So each rock type, from 1-5, should have one specific color, and the thickness of each colored bar should represent the thickness of that rock type. How can I achieve this?
Aggregate per type
You can find the total thickness of each rock type by using accumarray:
total_type_thickness = accumarray(A(:,1),A(:,2));
It sums up all values of the second column with equal number in the first column. So for your example data, this returns:
total_type_thickness =
72.5000
349.5000
52.0000
6.5000
19.5000
The difficult thing is displaying it as a single stacked bar, you can try using this workaround:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/57304
which leaves you with an empty column, which you can hide by setting the x limits:
bar([total_type_thickness'; zeros(size(total_type_thickness'))],'stacked');
xlim([0.25 1.75])
% add a legend with 'Rock Type <ii>'
legend(arrayfun(#(ii) sprintf('Rock type %d',ii), 1:length(total_type_thickness), 'uni',false));
For now, I haven't found a better alternative, as matlab won't stack the bars if you input vector data, it plots the bars separately in that case..
Display all values, same color per type
For plotting all the data (all layers), you can use the same approach, but now set the color data manually with colormap:
N = size(A,1); % number of layers
M = max(A(:,1)); % number of different rock types
bar([A(:,2)' ; NaN(1,N)],'stacked','facecolor','flat');
xlim([0.25 1.75])
cc = jet(M); % create colormap with N different colors
colormap(cc(A(:,1),:)); % pick for each layer, the correct color and use it as a colormap
For easier adding a legend, I'll add M dummy values to the original data:
bar([NaN(1,M) A(:,2)' ; NaN(1,N+M)],'stacked','facecolor','flat');
xlim([0.25 1.75])
cc = jet(M); % create colormap with N different colors
colormap(cc([(1:M)' ;A(:,1)],:)); % pick for each layer, the correct color and use it as a colormap
Now the first M elements in the legend will correspond to Rock type 1,2,.. M:
legend(arrayfun(#(ii) sprintf('Rock type %d',ii), 1:length(total_type_thickness), 'uni',false));