making repetitive code less clunky

2 次查看(过去 30 天)
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 个评论
DGM
DGM 2021-10-25
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. 2021-10-25
Thank you for pointing this out, I will correct this

请先登录,再进行评论。

采纳的回答

DGM
DGM 2021-10-25
编辑:DGM 2021-10-25
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 个评论
C.G.
C.G. 2021-10-25
编辑:C.G. 2021-10-25
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 2021-10-26
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.

请先登录,再进行评论。

更多回答(1 个)

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

类别

Help CenterFile Exchange 中查找有关 Historical Contests 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by