making repetitive code less clunky
조회 수: 1 (최근 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
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;
채택된 답변
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)
immse(y,y_1)
댓글 수: 2
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]
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
2021년 10월 25일
I would try using discretize to bin the data into groups then use groupsummary to compute the max on each group.
댓글 수: 0
참고 항목
카테고리
Help Center 및 File Exchange에서 Matrices and Arrays에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!