我在Matlab中有一个矩阵S,如下所示:
2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1
我想按列计算值的模式。我对任何列中编号3后后面的数字的频率感兴趣。例如,数字3在第一列中出现三次。我们第一次观察它时,接着是3次,第二次接着是3次,第三次接着是4.因此,在第一列中观察到的图案的频率看起来像是:
3-3: 66.66%
3-4: 33.33%
3-1: 0%
3-2: 0%
答案 0 :(得分:2)
这是一种方法,找到3'然后查看以下数字
[i,j]=find(S==3);
k=i+1<=size(S,1);
T=S(sub2ind(size(S),i(k)+1,j(k))) %// the elements of S that are just below a 3
R=arrayfun(@(x) sum(T==x)./sum(k),1:max(S(:))).' %// get the number of probability of each digit
答案 1 :(得分:2)
我将以我能理解的方式重述您的问题陈述,我的解决方案将反映这一新的问题陈述。
我们可以通过以下方式做到这一点:
A = [2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1]; %// Define your matrix
[row,col] = find(A(1:end-1,:) == 3);
vals = A(sub2ind(size(A), row+1, col));
h = 100*accumarray(vals, 1) / numel(vals)
h =
0
0
66.6667
33.3333
让我们慢慢浏览上面的代码。前几行定义了您的示例矩阵A
。接下来,我们会查看矩阵的所有行除了最后一行,并查看数字3与find
的位置。我们跳过最后一行,因为我们希望确保我们在矩阵的范围内。如果在最后一行有一个数字3,如果我们试图检查最后一行以下的值,我们会有未定义的行为,因为那里什么都没有!
一旦我们这样做,我们就会看一下矩阵中那些数字为3的那些值。我们使用sub2ind
来帮助我们实现这一点。接下来,我们使用这些值并使用accumarray
计算它们,然后将它们的总和归一化为百分比。
结果将是一个4元素数组,显示每个数字遇到的百分比。
要仔细检查,如果我们查看矩阵,我们会看到3的值跟随其他值3,总共4次 - 第一列,第3行,第4行,第二列,第2行和第3列,第6行。值4遵循3的值两次:第一列,第6行,第二列,第3行。
总共,我们计算了6个数字,因此除以6得到数字3和2/6的4/6或66.67%或数字4的33.33%。
答案 2 :(得分:2)
要生成输出,您可以使用方便的tabulate
S = [
2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1];
idx = find(S(1:end-1,:)==3);
S2 = S(2:end,:);
tabulate(S2(idx))
Value Count Percent
1 0 0.00%
2 0 0.00%
3 4 66.67%
4 2 33.33%
答案 3 :(得分:1)
如果我正确地得到了问题陈述,你可以用MATLAB's logical indexing
和一种基本上两行的方法有效地实现这个 -
%// Input 2D matrix
S = [
2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1]
Labels = [1:4]'; %//'# Label array
counts = histc(S([false(1,size(S,2)) ; S(1:end-1,:) == 3]),Labels)
Percentages = 100*counts./sum(counts)
下面列出的用于显示输出结果的样式使用MATLAB's table
来获取人类可读的数据格式。
风格#1
>> table(Labels,Percentages)
ans =
Labels Percentages
______ ___________
1 0
2 0
3 66.667
4 33.333
风格#2
你可以做一些奇特的字符串操作,以更“代表性”的方式呈现结果 -
>> Labels_3 = strcat('3-',cellstr(num2str(Labels','%1d')'));
>> table(Labels_3,Percentages)
ans =
Labels_3 Percentages
________ ___________
'3-1' 0
'3-2' 0
'3-3' 66.667
'3-4' 33.333
样式#3
如果您想根据问题的预期输出部分中列出的百分比以降序排列方式显示它们,您可以使用sort
-
>> [Percentages,idx] = sort(Percentages,'descend');
>> Labels_3 = strcat('3-',cellstr(num2str(Labels(idx)','%1d')'));
>> table(Labels_3,Percentages)
ans =
Labels_3 Percentages
________ ___________
'3-3' 66.667
'3-4' 33.333
'3-1' 0
'3-2' 0
现在,让我们假设你想重复这个过程来说1
,2
和4
,即在1
,2
之后找到匹配项和4
分别。在这种情况下,您可以针对所有情况迭代上述步骤,同样可以使用arrayfun
-
%// Get counts
C = cell2mat(arrayfun(@(n) histc(S([false(1,size(S,2)) ; S(1:end-1,:) == n]),...
1:4),1:4,'Uni',0))
%// Get percentages
Percentages = 100*bsxfun(@rdivide, C, sum(C,1))
给我们 -
Percentages =
90.9091 20.0000 0 100.0000
9.0909 20.0000 0 0
0 60.0000 66.6667 0
0 0 33.3333 0
因此,在Percentages
中,第一列是在输入矩阵中某处[1,2,3,4]
之后发生的1
计数。举个例子,当在输入矩阵中column -3
之后查找元素时,可以看到Percentages
3
是示例输出中的{{1}}。
答案 4 :(得分:1)
如果您想为每列独立计算的频率:
S = [2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1]; %// data: matrix
N = 3; %// data: number
r = max(S(:));
[R, C] = size(S);
[ii, jj] = find(S(1:end-1,:)==N); %// step 1
count = full(sparse(S(ii+1+(jj-1)*R), jj, 1, r, C)); %// step 2
result = bsxfun(@rdivide, count, sum(S(1:end-1,:)==N)); %// step 3
其工作原理如下:
find
来确定N
中S
除了最后一行之外的count
次出现的行和列索引。S
中为每列累积条目正下方步骤1的索引中的值。非常方便的sparse
函数用于此目的。请注意,这会将linear indexing用于count
。N
除以每列中result =
0 0 0 NaN
0 0 0 NaN
0.6667 0.5000 1.0000 NaN
0.3333 0.5000 0 NaN
的出现次数(bsxfun
)。此示例中的结果是
NaN
请注意,最后一列正确包含{{1}} s,因为该列的搜索模式的频率未定义。