MATLAB Answers

How to divide the curve into two sections and then fit straight line for both sections separately and get intersection of the lines?

4 views (last 30 days)
AB
AB on 6 Mar 2020
Commented: AB on 8 Mar 2020
The curve is a continuous data set with around 2000 or so data points in excel. I want to import it first and then divide the curve into two sections and fit the staright line for each section separately.Then get a point of intersection of two straight lines and get intersection co-ordinates.

  0 Comments

Sign in to comment.

Answers (4)

Image Analyst
Image Analyst on 7 Mar 2020
Sorry for the delay. I'm sure you definitely figured it out by now, but for what it's worth, here it is for the first data set:
% Initialization steps:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
markerSize = 15;
% Read in data from Excel workbook.
[numbers, strings, raw] = xlsread('combined_data.xlsx')
% Get first data set. Eliminate nan values.
x = numbers(:, 1);
x(isnan(x)) = [];
y = numbers(:, 2);
y(isnan(y)) = [];
numPoints = length(x)
hFig = figure;
subplot(2, 2, 1);
plot(x, y, 'b-', 'LineWidth', 2);
grid on;
xlabel('x', 'FontSize', fontSize);
ylabel('y', 'FontSize', fontSize);
title('Original Data', 'FontSize', fontSize);
hFig.WindowState = 'maximized'; % Maximize window.
% Assume the crossing point will be somewhere in the middle 80% of the points.
% Fit a line through the right and left parts and get the slopes.
% Keep the point where the slope difference is greatest.
index1 = round(0.1 * numPoints); % 10% of the way through.
index2 = round(0.9 * numPoints); % 90% of the way through.
% In other words, assume that we need at least 10 percent of the points to make a good estimate of the line.
% Obviously if we took only 2 or 3 points, then the slope could vary quite dramatically,
% so let's use at least 10% of the points to make sure we don't get crazy slopes.
% Initialize structure array
for k = 1 : numPoints
lineData(k).slopeDifferences = 0;
lineData(k).line1 = [0,0];
lineData(k).line2 = [0,0];
end
for k = index1 : index2
% Get data in left side.
x1 = x(1:k);
y1 = y(1:k);
% Fit a line through the left side.
coefficients1 = polyfit(x1, y1, 1); % The slope is coefficients1(1).
% Get data in right side.
x2 = x(k+1:end);
y2 = y(k+1:end);
% Fit a line through the left side.
coefficients2 = polyfit(x2, y2, 1); % The slope is coefficients2(1).
% Compute difference in slopes, and store in structure array along with line equation coefficients.
lineData(k).slopeDifferences = abs(coefficients1(1) - coefficients2(1));
lineData(k).line1 = coefficients1;
lineData(k).line2 = coefficients2;
end
% Find index for which slope difference is greatest.
slopeDifferences = [lineData.slopeDifferences]; % Extract from structure array into double vector of slope differences only
% slope1s = struct2table(lineData.line1); % Extract from structure array into double vector of slopes only
% slope2s = [lineData.line2(1)]; % Extract from structure array into double vector of slopes only
[maxSlopeDiff, indexOfMaxSlopeDiff] = max(slopeDifferences)
% Plot slope differences.
subplot(2, 2, 2);
plot(slopeDifferences, 'b.', 'MarkerSize', markerSize);
xlabel('Index', 'FontSize', fontSize);
ylabel('Slope Difference', 'FontSize', fontSize);
grid on;
caption = sprintf('Slope Differences Maximum at Index = %d, x value = %.2f', indexOfMaxSlopeDiff, x(indexOfMaxSlopeDiff));
title(caption, 'FontSize', fontSize);
% Mark it with a red line.
line([indexOfMaxSlopeDiff, indexOfMaxSlopeDiff], [0, maxSlopeDiff], 'Color', 'r', 'LineWidth', 2);
% Show everything together all on one plot.
% Plot lines.
subplot(2, 2, 3:4);
plot(x, y, 'b.', 'MarkerSize', markerSize);
grid on;
xlabel('x', 'FontSize', fontSize);
ylabel('y', 'FontSize', fontSize);
hold on;
% Use the equation of line1 to get fitted/regressed y1 values.
slope1 = lineData(indexOfMaxSlopeDiff).line1(1);
intercept1 = lineData(indexOfMaxSlopeDiff).line1(2);
y1Fitted = slope1 * x + intercept1;
% Plot line 1 over/through data.
plot(x, y1Fitted, 'r-', 'LineWidth', 2);
% Use the equation of line2 to get fitted/regressed y2 values.
slope2 = lineData(indexOfMaxSlopeDiff).line2(1);
intercept2 = lineData(indexOfMaxSlopeDiff).line2(2);
y2Fitted = slope2 * x + intercept2;
% Plot line 2 over/through data.
plot(x, y2Fitted, 'r-', 'LineWidth', 2);
% Mark crossing with a magenta line.
xc = (intercept2 - intercept1) / (slope1 - slope2);
xline(xc, 'Color', 'm', 'LineWidth', 2);
title('Data with left and right lines overlaid', 'FontSize', fontSize);
message1 = sprintf('Left Equation: y = %.3f * x + %.3f', slope1, intercept1);
message2 = sprintf('Right Equation: y = %.3f * x + %.3f', slope2, intercept2);
message = sprintf('%s\n%s', message1, message2);
fprintf('%s\n', message);
text(27, 7, message, 'Color', 'r', 'FontSize', 15, 'FontWeight', 'bold');
uiwait(helpdlg(message));
You'll notice that I picked a splitting point at every index from 10% of the way through until 90% of the way through and computed lines on each side of that split point. Then I looked at, and plotted in the upper left graph, the difference in slopes between the right line and left line. The best intersection point will be where the difference in slopes is greatest. You'll see this printed out:
maxSlopeDiff =
0.292467879717763
indexOfMaxSlopeDiff =
167
Left Equation: y = 0.003 * x + 4.042
Right Equation: y = 0.295 * x + -5.968
so you can see that at index 167, which is x=34.3, is the best place to split the curve up into two linear segments, and the equation of the lines on each side are given.
Did this match what you got for the two line equations? It should. Then you repeated it for the other two data sets, right? How did that work out?

  0 Comments

Sign in to comment.


Star Strider
Star Strider on 7 Mar 2020
And of course —
T1 = readtable('combined_data.xlsx');
A = str2double(table2array(T1(2:end,:)));
figure
Cm = lines(fix(size(A,2)/2));
hold on
for k = 1:fix(size(A,2)/2)
x = A(:,1+2*(k-1));
y = A(:,2+2*(k-1));
cp{k} = ischange(y, 'linear', 'Threshold',0.25); % Find Change Points
cpidx{k} = find(cp{k}, 2, 'first'); % Change Point Indices
hl{k} = plot(x, y, ':', 'Color',Cm(k,:)); % Plot Raw Data
C = hl{k}.Color;
idxrng = {1:cpidx{k}(1); cpidx{k}(1):cpidx{k}(2)}; % Index Range For This Data Set
xr1 = x(idxrng{1}); % Data For Linear Regression
yr1 = y(idxrng{1}); % Data For Linear Regression
xr2 = x(idxrng{2}); % Data For Linear Regression
yr2 = y(idxrng{2}); % Data For Linear Regression
B{k,1} = [xr1(:) ones(size(xr1(:)))] \ yr1(:); % Estimate Parameters: First Set
B{k,2} = [xr2(:) ones(size(xr2(:)))] \ yr2(:); % Estimate Parameters: Second Set
% plot(x(cpidx{k}), y(cpidx{k}), '^', 'MarkerFaceColor',C, 'MarkerSize',10) % Plot Change Points (Un-Comment This Line To See Them)
yf1 = [xr1(:) ones(size(xr1(:)))] * B{k,1}; % Fit First Regression Line
yf2 = [xr2(:) ones(size(xr2(:)))] * B{k,2}; % Fit Second Regression Line
plot(xr1, yf1, 'Color',C, 'LineWidth',2) % Plot First Regression Line
plot(xr2, yf2, 'Color',C, 'LineWidth',2) % Plot Second Regression Line
xint(k,:) = (B{k,1}(2)-B{k,2}(2)) / (B{k,2}(1)-B{k,1}(1)); % Solve For ‘x’ Intersection
yint(k,:) = [xint(k) 1] * B{k,1}; % Solve For ‘y’ Intersection
% pause(5)
end
hold off
grid
legend([hl{:}], {'Columns 1:2','Columns 3:4','Columns 5:6'}, 'Location','E')
Regressions = array2table([B{:,1};B{:,2}], 'VariableNames',{'Cols_12','Cols_34','Cols_56'}, 'RowNames',{'Slope_1','Intercept_1','Slope_2','Intercept_2'})
Intersections = table(xint, yint, 'VariableNames',{'X_Intersect','Y_Intersect'}, 'RowNames',{'Cols_12','Cols_34','Cols_56'})
producing:
Regressions =
Cols_12 Cols_34 Cols_56
_________ _________ ________
Slope_1 0.0027788 0.0022421 0.003146
Intercept_1 4.0321 4.0616 4.0364
Slope_2 0.32669 0.30598 0.64086
Intercept_2 -6.9594 -7.1488 -19.264
Intersections =
X_Intersect Y_Intersect
___________ ___________
Cols_12 33.933 4.1264
Cols_34 36.908 4.1444
Cols_56 36.537 4.1513
and:

  0 Comments

Sign in to comment.


KSSV
KSSV on 6 Mar 2020
  1. Load the excel file into MATLAB using xlsread.
  2. Divide the data into sections using data1 = data(1:1000,:) ; data2 = data(1001:2000,:) ;
  3. Fit the staright line to each data/ curve using polyfit. Evaluate the values using polyval.
  4. Find the intersection of lines using InterX available from the link: https://in.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections?focused=5165138&tab=function

  9 Comments

Show 6 older comments
KSSV
KSSV on 6 Mar 2020
Did you copy the function in the working folder? The error clearly says it is unable to find the function InterX.
AB
AB on 6 Mar 2020
No. I'm sorry but Im very new to Matlab. So would you mind letting me know how exactly do I copy the function in working folder?

Sign in to comment.


Image Analyst
Image Analyst on 6 Mar 2020

  4 Comments

Show 1 older comment
KSSV
KSSV on 6 Mar 2020
Download the function which is give in the link.......copy the file InterX.m into the present working directory.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!

Translated by