Slope of some groups of data separated by NaNs

조회 수: 80 (최근 30일)
Adi Purwandana
Adi Purwandana 2024년 10월 29일 23:54
댓글: Star Strider 2024년 11월 1일 13:53
Hello there,
I have a dataset containing two variable, dx and z (please check attached file). The dx contain some groups of values separated by NaN. My intention is getting the slope line and its slope value for each group as shown below. Note that the dx values in each group contain/cross the negative and positive values. Thanks!
load('data_mine.mat');
figure;
scatter(dx,z);
set(gca, 'YDir','reverse')

채택된 답변

Star Strider
Star Strider 2024년 10월 30일 1:44
I am not certain what you want for ‘values’.
This prints the equation of the regression line for each line —
load('data_mine.mat')
whos('-file','data_mine.mat')
Name Size Bytes Class Attributes dx 1x893 7144 double z 1x893 7144 double
nanv = [0 ~isnan(dx) 0];
nanstart = strfind(nanv, [0 1]);
nanend = strfind(nanv, [1 0])-1;
nanmtx = [nanstart; nanend];
% [dxi,dx2] = bounds(dx)
[z1,z2] = bounds(z);
z1 = 5
z2 = 451
figure
scatter(dx,z)
set(gca, 'YDir','reverse')
hold on
for k = 1:size(nanmtx,2)
idxrng = nanmtx(1,k):nanmtx(2,k);
DM = [dx(idxrng); ones(size(idxrng))].';
B(:,k) = DM \ z(idxrng).';
x{k} = dx(idxrng);
y{k} = DM * B(:,k);
plot(x{k}, y{k}, '-g')
text(max(x{k}), max(y{k}), sprintf(' \\leftarrow z = %.3f \\cdot dx %+.3f', B(:,k)), 'Horiz','left', 'Vert','middle')
end
hold off
axis([-15 20 z1 z2])
xlabel('dx')
ylabel('z')
title('Entire Data Set')
B
B = 2×22
0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 0.4466 5.5000 11.2500 32.2500 35.5000 41.7500 106.0000 117.0000 127.7500 154.7500 270.2500 300.5000 330.7500 350.5000 359.5000 374.5000 389.2500 404.2500 410.0000 434.5000 437.2500 442.0000 448.6241
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
figure
scatter(dx,z)
set(gca, 'YDir','reverse')
hold on
for k = 1:size(nanmtx,2)
idxrng = nanmtx(1,k):nanmtx(2,k);
DM = [dx(idxrng); ones(size(idxrng))].';
% B(:,k) = DM \ z(idxrng).';
x{k} = dx(idxrng);
y{k} = DM * B(:,k);
plot(x{k}, y{k}, '-g')
text(max(x{k}), max(y{k}), sprintf(' \\leftarrow z = %.3f \\cdot dx %+.3f', B(:,k)), 'Horiz','left', 'Vert','middle')
end
hold off
axis([-15 20 100 135])
xlabel('dx')
ylabel('z')
title('Detail')
The regression coefficients are in the ‘B’ matrix, with the slope in the first row and intercept in tthe second row for each line.
.
  댓글 수: 15
Adi Purwandana
Adi Purwandana 2024년 11월 1일 13:20
Perfect! Thank you very much!
Star Strider
Star Strider 2024년 11월 1일 13:53
As always, my pleasure!
This was an interesting problem!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Umar
Umar 2024년 10월 30일 1:25

Hi @Adi Purwandana,

After reviewing your comments, and analyzing the dataset data_mine.mat in matlab shown below

Name      Size             Bytes   Class     Attributes
dx        1x893            7144   double              
z         1x893            7144   double   

You are right that it contains two variables, dx and z. As you mentioned that dx having groups of values separated by NaNs, first import the .mat. file to access the variables as shown in your code snippet. Then, split the dx values into separate groups based on the NaN values. For each group, fit a linear regression model to determine the slope and then visualize each group along with its corresponding slope line. Here is a full code example in MATLAB that accomplishes this:

% Load the dataset
load('data_mine.mat');
% Initialize variables
dx_groups = {};
z_groups = {};
current_group_dx = [];
current_group_z = [];
% Split dx and z into groups based on NaN in dx
for i = 1:length(dx)
  if isnan(dx(i))
      if ~isempty(current_group_dx) % Only save if current group is not empty
          dx_groups{end + 1} = current_group_dx; %#ok<AGROW>
          z_groups{end + 1} = current_group_z; %#ok<AGROW>
          current_group_dx = []; % Reset for next group
          current_group_z = []; % Reset for next group
      end
    else
      current_group_dx(end + 1) = dx(i); %#ok<AGROW>
      current_group_z(end + 1) = z(i); %#ok<AGROW>
  end
end
% Add last group if it exists
if ~isempty(current_group_dx)
  dx_groups{end + 1} = current_group_dx; %#ok<AGROW>
  z_groups{end + 1} = current_group_z; %#ok<AGROW>
end
% Initialize figure for plotting
figure;
hold on;
% Analyze each group and plot results
for g = 1:length(dx_groups)
  % Extract current group
  x = dx_groups{g};
  y = z_groups{g};
    % Perform linear regression to find slope
    p = polyfit(x, y, 1); % p(1) is the slope, p(2) is the intercept
    % Generate x values for plotting the fitted line
    x_fit = linspace(min(x), max(x), 100);
    y_fit = polyval(p, x_fit);
    % Plot original data points
    plot(x, y, 'o', 'DisplayName', ['Group ' num2str(g)]);
    % Plot the fitted line
    plot(x_fit, y_fit, 'LineWidth', 2, 'DisplayName', ['Slope: ' num2str(p(1))]);
  end
% Finalize plot settings
xlabel('dx');
ylabel('z');
title('Slope Analysis of Groups in dx');
legend show;
grid on;
hold off;
% Display slopes for each group in command window
for g = 1:length(dx_groups)
  fprintf('Group %d: Slope = %.4f\n', g, polyfit(dx_groups{g}, z_groups{g}, 
  1));
end

Please see attached.

As you will notice that the code starts by loading the data_mine.mat file.It loops through dx, collecting values until a NaN is encountered. Each segment is stored in separate cell arrays (dx_groups and z_groups). For each group of data points, a linear fit is performed using polyfit, which returns coefficients for a linear equation (y = mx + b). For more information on this function, please refer to polyfit

Each group’s data points and corresponding fitted line are plotted. The slopes are displayed in the legend and printed to the console. Adjust visualization parameters (like colors or markers) based on your preferences or specific requirements.

Hope this helps.

Please let me know if you have any further questions.

카테고리

Help CenterFile Exchange에서 Annotations에 대해 자세히 알아보기

태그

제품


릴리스

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by