making repetitive code less clunky
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
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 Kommentare
DGM
am 25 Okt. 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;
Akzeptierte Antwort
DGM
am 25 Okt. 2021
Bearbeitet: DGM
am 25 Okt. 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 Kommentare
DGM
am 26 Okt. 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.
Weitere Antworten (1)
Steven Lord
am 25 Okt. 2021
I would try using discretize to bin the data into groups then use groupsummary to compute the max on each group.
0 Kommentare
Siehe auch
Kategorien
Mehr zu Matrices and Arrays finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!