making repetitive code less clunky

2 vues (au cours des 30 derniers jours)
C.G.
C.G. le 25 Oct 2021
Commenté : DGM le 26 Oct 2021
My code works, but its very long winded. I didnt know if there was a way this could be simplified to get the same outcome?
I want to reduce the range of S1-S6 to smaller intervals but dont want to have to write all the lines out all the time.
%% Input files
file = dir('*.csv'); %read the files into matlab
num_files = length(file); %record how many files have been found
%% Calculate the x and y coordinates for the highest particle in each segment for each time step
for a = 1:num_files
T = table2array(readtable(filelist(a).name)); %read in the values
T = T(T(:,6)<=-0.07,:);
%s1
S1 = T(:,5) >= 0.146 & T(:,5) <= 0.149;
TS1 = T(S1, :);
[y1(a), idx1] = max(TS1(:, 6));
x1(a) = TS1(idx1, 5);
%s2
S2 = T(:,5) >= 0.141 & T(:,5) <= 0.145;
TS2 = T(S2, :);
[y2(a), idx2] = max(TS2(:, 6));
x2(a) = TS2(idx2, 5);
%s3
S3 = T(:,5) >= 0.136 & T(:,5) <= 0.14;
TS3 = T(S3, :);
[y3(a), idx3] = max(TS3(:, 6));
x3(a) = TS3(idx3, 5);
%s4
S4 = T(:,5) >= 0.131 & T(:,5) <= 0.135;
TS4 = T(S4, :);
[y4(a), idx4] = max(TS4(:, 6));
x4(a) = TS4(idx4, 5);
%s5
S5 = T(:,5) >= 0.126 & T(:,5) <= 0.13;
TS5 = T(S5, :);
[y5(a), idx5] = max(TS5(:, 6));
x5(a) = TS5(idx5, 5);
%s6
S6 = T(:,5) >= 0.121 & T(:,5) <= 0.125;
TS6 = T(S6, :);
[y6(a), idx6] = max(TS6(:, 6));
x6(a) = TS6(idx6, 5)
x = [x1; x2; x3; x4; x5; x6];
y = [y1; y2; y3; y4; y5; y6];
%check the coordinates in a plot
figure(1)
cla;
scatter(x(:,a),y(:,a))
xlabel('X Coordinates')
ylabel('Y Coordinates')
title('Particle locations in the rice pile')
set(gca, 'XDir','reverse')
L = 0.08:0.0025:0.15 ;
for i = 1:length(L)
xline(L(i));
end
hold on
pause(0.5)
end
  2 commentaires
DGM
DGM le 25 Oct 2021
Off-topic, but the union of your threshold windows is not a continuous range. For instance,
S1 = T(:,5) >= 0.146 & T(:,5) <= 0.149;
% ...
S2 = T(:,5) >= 0.141 & T(:,5) <= 0.145;
An input value of 0.1455 will not be selected by either operation. One way to avoid this is to use the same breakpoints, paying attention to equality conditions so that the sets don't intersect.
S1 = T(:,5) > 0.146 & T(:,5) <= 0.149;
% ...
S2 = T(:,5) > 0.141 & T(:,5) <= 0.146;
C.G.
C.G. le 25 Oct 2021
Thank you for pointing this out, I will correct this

Connectez-vous pour commenter.

Réponse acceptée

DGM
DGM le 25 Oct 2021
Modifié(e) : DGM le 25 Oct 2021
You could simplify this with a loop if you wanted, though I'm sure there are other ways. Bear in mind what I mentioned in my comment. You may have to adjust your breakpoints to suit your needs. This is just an example.
a = 1;
num_files = 1;
T = rand(30,6)*0.030 + 0.120;
%s1
S1 = T(:,5) > 0.145 & T(:,5) <= 0.150;
TS1 = T(S1, :);
[y1(a), idx1] = max(TS1(:, 6));
x1(a) = TS1(idx1, 5);
%s2
S2 = T(:,5) > 0.140 & T(:,5) <= 0.145;
TS2 = T(S2, :);
[y2(a), idx2] = max(TS2(:, 6));
x2(a) = TS2(idx2, 5);
%s3
S3 = T(:,5) > 0.135 & T(:,5) <= 0.140;
TS3 = T(S3, :);
[y3(a), idx3] = max(TS3(:, 6));
x3(a) = TS3(idx3, 5);
%s4
S4 = T(:,5) > 0.130 & T(:,5) <= 0.135;
TS4 = T(S4, :);
[y4(a), idx4] = max(TS4(:, 6));
x4(a) = TS4(idx4, 5);
%s5
S5 = T(:,5) > 0.125 & T(:,5) <= 0.130;
TS5 = T(S5, :);
[y5(a), idx5] = max(TS5(:, 6));
x5(a) = TS5(idx5, 5);
%s6
S6 = T(:,5) > 0.120 & T(:,5) <= 0.125;
TS6 = T(S6, :);
[y6(a), idx6] = max(TS6(:, 6));
x6(a) = TS6(idx6, 5);
x_1 = [x1; x2; x3; x4; x5; x6];
y_1 = [y1; y2; y3; y4; y5; y6];
% do the same thing in a loop instead
bp = 0.150:-0.005:0.120; % breakpoints
x = zeros(numel(bp)-1,num_files); % preallocate
y = zeros(size(x));
for k = 1:numel(bp)-1
S = T(:,5) > bp(k+1) & T(:,5) <= bp(k);
TS = T(S, :);
[y(k,a), idx] = max(TS(:, 6));
x(k,a) = TS(idx, 5);
end
% results match
immse(x,x_1)
ans = 0
immse(y,y_1)
ans = 0
  2 commentaires
C.G.
C.G. le 25 Oct 2021
Modifié(e) : C.G. le 25 Oct 2021
thats exactly what I was looking for, thank you.
I have tried changing this line to have intervals of 0.0025, but im getting the error
bp = 0.150:-0.005:0.120
Unable to perform assignment because the size of the left side is 1-by-1 and the size of the right side is 0-by-1.
DGM
DGM le 26 Oct 2021
Oh. That's just an artifact of the example itself having so few samples that some bins randomly wind up empty. For a fixed number of samples, reducing bin size increases the probability that any given bin will be empty. If I make T larger, it tends to work.
a = 1;
num_files = 1;
T = rand(100,6)*0.030 + 0.120;
% do the same thing in a loop instead
bp = 0.150:-0.0025:0.120; % breakpoints
x = zeros(numel(bp)-1,num_files); % preallocate
y = zeros(size(x));
for k = 1:numel(bp)-1
S = T(:,5) > bp(k+1) & T(:,5) <= bp(k);
TS = T(S, :);
[y(k,a), idx] = max(TS(:, 6));
x(k,a) = TS(idx, 5);
end
[x y]
ans = 12×2
0.1478 0.1497 0.1467 0.1441 0.1430 0.1493 0.1404 0.1448 0.1394 0.1496 0.1353 0.1491 0.1325 0.1473 0.1323 0.1468 0.1288 0.1486 0.1269 0.1458
If your data itself has the same issue, you would need to decide how to handle cases where a given bin is empty. Perhaps it would suffice to test S and skip that cycle, leaving that x,y pair as zero. Otherwise, you might use NaN as a placeholder instead of zero in those cases.
for k = 1:numel(bp)-1
S = T(:,5) > bp(k+1) & T(:,5) <= bp(k);
if nnz(S) == 0
x(k,a) = NaN;
y(k,a) = NaN;
else
TS = T(S, :);
[y(k,a), idx] = max(TS(:, 6));
x(k,a) = TS(idx, 5);
end
end
Steven's answer may be more useful, but it's not a workflow that I am familiar with.

Connectez-vous pour commenter.

Plus de réponses (1)

Steven Lord
Steven Lord le 25 Oct 2021
I would try using discretize to bin the data into groups then use groupsummary to compute the max on each group.

Catégories

En savoir plus sur Historical Contests dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by