如何在Matlab中按列计算模式?
我在Matlab中有一个矩阵S,如下所示:如何在Matlab中按列计算模式?,matlab,matrix,frequency,Matlab,Matrix,Frequency,我在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.
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%
这里有一种方法,找到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
[i,j]=find(S==3);
k=i+1我将以我能理解的方式重申你的问题陈述,我的解决方案将反映这个新的问题陈述
对于特定列,找到包含数字3的位置李>
查看这些位置正下方的行,并查看这些位置的值
获取这些值并汇总找到的事件总数
对所有列重复这些操作并更新计数,然后确定值的出现百分比
我们可以通过以下方式做到这一点:
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的位置。我们跳过最后一行,因为我们想确保我们在矩阵的范围内。如果最后一行有一个数字3,那么如果我们试图检查最后一行下面的值,我们将有未定义的行为,因为那里什么都没有
一旦我们这样做了,我们就来看看矩阵中的那些值,它们比那些数字3低1行。我们经常帮助我们促进这一点。下一步,我们使用这些值并使用将它们汇总,然后通过汇总的总和将它们规格化为百分比
结果将是一个4元素数组,显示每个数字所遇到的百分比
为了再次检查,如果我们查看矩阵,我们会看到值3跟随其他值3,总共4次-第一列,第3行,第4行,第二列,第2行和第三列,第6行。值4跟随值3两次:第一列,第6行,第二列,第3行
总的来说,我们计算了6个数字,因此除以6,我们得到数字3的4/6或66.67%,数字4的2/6或33.33%。如果我得到了正确的问题陈述,您可以使用基本上由两行组成的方法有效地实现这一点-
%// 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)
验证/呈现结果
下一步列出的显示输出结果的样式将用于可读性良好的数据格式
风格#1
>> table(Labels,Percentages)
ans =
Labels Percentages
______ ___________
1 0
2 0
3 66.667
4 33.333
风格#2
您可以执行一些奇特的字符串操作,以更具“代表性”的方式显示结果-
风格#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
因此,在百分比
中,第一列是[1,2,3,4]
的计数,这些计数发生在输入矩阵中某个地方出现1
之后。例如,在输入矩阵中查找3
之后的元素时,可以看到百分比的列-3
就是示例输出中的元素。要生成输出,可以使用
如果要独立计算每列的频率:
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
这项工作如下:
首先用于确定除最后一行以外的S
中出现的N
的行和列索引
步骤1索引正下方的条目中的值在变量count
中为每列累加。为此目的使用了非常方便的功能。请注意,这将使用intoS
为了获得每列的频率,count
除以每列中出现的N
的次数
本例中的结果是
result =
0 0 0 NaN
0 0 0 NaN
0.6667 0.5000 1.0000 NaN
0.3333 0.5000 0 NaN
请注意,最后一列正确地包含NaN
s,因为该列未定义查找模式的频率。我不理解您的问题陈述。您能告诉我们您是如何计算这些值的吗?上面提供的百分比是假设的,与特定矩阵S中的确切百分比不一致。我们的想法是找出1/2/3/4在矩阵的列中跟在数字3后面的次数。好吧,我还是不明白。你需要帮我把它分解一下。想象一下,我是一个5岁的孩子。让我们看一下第一栏。是否要计算数字3后面的1、2、3或4的值的倍数?正如我所说,举例计算有助于理解你的观点。还有,这些百分比意味着什么?谢谢你的提问。在第一列中,数字3出现三次。我们第一次观察它,它后面跟着3,第二次它后面跟着3,第三次它后面跟着4。因此,在第一列中观察到的模式频率看起来像3-3:66.66%和3-4:33.33%,而没有观察到3-1:0%和3-2:0%的组合。对于SO社区:
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
result =
0 0 0 NaN
0 0 0 NaN
0.6667 0.5000 1.0000 NaN
0.3333 0.5000 0 NaN