问题描述
我有50个电子表格,其中包含多个计分栏: 一列(AG)的数字编码为1:13,另一列(SEC)的数字编码为1:6。
例如:
AG SEC
1 1
2 1
4 1
13 1
3 2
12 2
我想编写一个for循环,计算.SEC中与.AG中的#s 1:5对应的所有1。 (输出将为3-不会计算与13对应的1)。我需要在.SEC(1:6)中的所有#事件中都发生这种情况。最终输出将在第一列中包含电子表格名称,并在每个后续列中将.SEC = 1,2,3,4,5,6计数。
我当前的代码为.SEC中的.AG总数创建了一个变量,但没有区别(计算.AG中任何数字的次数,而不是计算特定值)
scoringfiles
是一个50个项目的路径列表(当我执行readtable(scoringfiles)
时,它将遍历该列表并读取excel文件。filelist
是一个仅包含文件名的50个项目列表。
for i=1:length(scoringfiles)
if contains(filelist(i,:),"sheet")
disp(i)
sheetnum=[sheetnum extractBetween(filelist{i},1,4)]
s1=[s1 length(find(readtable(scoringfiles(i,:)).SEC==1))]
s2=[s2 length(find(readtable(scoringfiles(i,:)).SEC==2))]
s3=[s3 length(find(readtable(scoringfiles(i,:)).SEC==3))]
s4=[s4 length(find(readtable(scoringfiles(i,:)).SEC==4))]
s5=[s5 length(find(readtable(scoringfiles(i,:)).SEC==5))]
s6=[s6 length(find(readtable(scoringfiles(i,:)).SEC==6))]
elseif contains(filelist(i,"graph")
disp("not sheet")
end
end
解决方法
在MATLAB中,i
和j
是虚数单位。为了避免重新定义它,您应该养成习惯使用ii
和jj
作为循环变量,而不是i
和j
。
现在回到主要问题:
假设您已将文件内容读入data
变量中。这将是一个Nx2
数组。
仅当AG处于1:5
范围内时,您才关心它。让我们用filter
创建一个true
数组,其中AG在范围内,false
在其他位置。
filter = data(:,1) >= 1 & data(:,1) <= 5;
为了清晰起见,我们首先将这些列分为两个变量。使用过滤器仅选择符合我们条件的行。
ag = data(filter,1);
sec = data(filter,2);
现在,您要遍历sec
中的每个 unique 值,并计算ag
条目的数量。
unique_sec = unique(sec);
counts = zeros(size(unique_sec)); % Preallocate a zeros array to save our answer in
for ii = 1:length(unique_sec)
sec_value = unique_sec(ii); % Get the value of SEC
matches = sec == sec_value; % Make a filter for rows that have this value
% matches is a logical array. true = 1,false = 0. sum gives number of trues.
counts(ii) = sum(matches);
end
或者,如果您不想在之前进行过滤,则可以在循环内对1 <= AG <= 5
进行过滤:
ag = data(:,1);
sec = data(:,2);
unique_sec = unique(sec);
counts = zeros(size(unique_sec));
for ii = 1:length(unique_sec)
sec_value = unique_sec(ii);
matches = sec == sec_value & ag >= 1 & ag <= 5; % Add more conditions to the filter
counts(ii) = sum(matches);
end
如果要对多个文件执行此操作,请遍历它们并将文件读取到data
变量中。
借助Pranav的帮助,我弄清楚了如何应用过滤器。就像在遍历我的电子表格中进行迭代一样,只需将过滤器添加到for循环的每一行即可。见下文:
此示例仅在S1和S2上可见。实际上,我有6个不同的#s来创建6个表,每个电子表格都有计数。
for i=1:length(scoringfiles)
filter1 = readtable(scoringfiles(i,:)).AG >= 1;
filter2 = readtable(scoringfiles(i,:)).AG <= 5;
if contains(filelist(i,:),"sheet")
disp(i)
sheetnum=[sheetnum extractBetween(filelist{i},1,4)]
s1=[s1 length(find(readtable(scoringfiles(i,:)).SEC==1 & filter1 & filter2))]
s2=[s2 length(find(readtable(scoringfiles(i,:)).SEC==2 & filter1 & filter2))]
elseif contains(filelist(i,"graph")
disp("not sheet")
end
end