Slope of some groups of data separated by NaNs

6 Ansichten (letzte 30 Tage)
Adi Purwandana
Adi Purwandana am 29 Okt. 2024
Kommentiert: Star Strider am 1 Nov. 2024
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')

Akzeptierte Antwort

Star Strider
Star Strider am 30 Okt. 2024
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 Kommentare
Adi Purwandana
Adi Purwandana am 1 Nov. 2024
Perfect! Thank you very much!
Star Strider
Star Strider am 1 Nov. 2024
As always, my pleasure!
This was an interesting problem!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Umar
Umar am 30 Okt. 2024

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.

Produkte


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by