# making repetitive code less clunky

6 views (last 30 days)

Show older comments

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

### Accepted Answer

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)

immse(y,y_1)

##### 2 Comments

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]

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

##### 0 Comments

### See Also

### Community Treasure Hunt

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

Start Hunting!