# making repetitive code less clunky

3 views (last 30 days)
C.G. on 25 Oct 2021
Commented: DGM on 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 CommentsShowHide 1 older comment
C.G. on 25 Oct 2021
Thank you for pointing this out, I will correct this

DGM on 25 Oct 2021
Edited: DGM on 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 CommentsShowHide 1 older comment
DGM on 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.

### More Answers (1)

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