How to divide a curve into two sections and fit straight lines for two sections in a curve separately and then find an intersection point of the lines. Kindly help

24 次查看(过去 30 天)
There is a curve with say 3000 data points. I need to plot it first and divide it into two sections and fit straight lines separately. Then get the intersection of those straight lines and get the co-ordinate points.

采纳的回答

Image Analyst
Image Analyst 2020-3-5
I do that in the attached piecewise fitting demo. It divides the data into two sections and fits lines to the left section and right section and finds out where the lines intersect. Then it determines at what splitting index is the slope between the left line and right line the greatest so determine the best place to split the signal up into two "linear" sections.
  5 个评论
Image Analyst
Image Analyst 2020-3-7
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?
AB
AB 2020-3-8
Thank you so much for the reply and the code. But there is a error message when i tried running this code in my system.
Error using xlsread (line 260)
Invoke Error, Dispatch Exception:
Source: Microsoft Excel
Description: Open method of Workbooks class failed
Help File: xlmain11.chm
Help Context ID: 0
Error in code_1 (line 13)
[numbers, strings, raw] = xlsread('combined_data.xlsx')
Does this mean there is error loading the file itself? How can I correct this?Kindly guide me.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Nonlinear Regression 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by