-3

我想控制这个矩阵中随机数的创建:

Mp = floor(1+(10*rand(2,20)));
mp1 = sort(Mp,2);

我想修改这段代码以获得这样的输出:

1 1 2 2 3 3 3 4 5 5 6 7 7 8 9 9 10 10 10 10
1 2 3 3 3 3 3 3 4 5 6 6 6 6 7 8 9  9  9  10 

我必须用从 1 到 10 的所有数字以递增的顺序填充每一行,计算每个数字出现次数的第二个矩阵应该是这样的:

1 2 1 2 1 2 3 1 1 2 1 1 2 1 1 2 1 2 3 4
1 1 1 2 3 4 5 6 1 1 1 2 3 4 1 1 1 2 3 1

自上周以来我一直在寻找的最棘手的矩阵是第三个矩阵,它应该浏览第一个矩阵的每一行并返回每个数字的出现次数和最后一次出现的位置。这是一个代码应该如何工作的示例。此示例显示了运行第一个矩阵的第一行后的预期结果。

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (positions)
1     2    
2         2
3               3
4                  1
5                      2              
6                         1
7                               2                    
8                                  1
9                                        2
10                                                    4

(数字)

此示例显示了运行第一个矩阵的第二行后的预期结果。

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (positions)
1   1 2    
2     1   2
3               3 6
4                  1 1
5                      3              
6                         1         4
7                               2      1              
8                                  1     1
9                                        2         3
10                                                    4

(数字)

所以想要的矩阵必须从一开始就用零填充,每次遍历第一个矩阵的每一行后,我们都会将新结果添加到前一个结果中......

4

3 回答 3

0

我正在编辑上一个答案以检查当 mp1 很大时它是否很快,显然它是:

N = 20000; M = 200; P = 100;
mp1 = sort([repmat(1:P, M, 1), ceil(P*rand(M,N-P))], 2);
tic
% Initialise output matrices
out1 = zeros(M, N); out2 = zeros(P, N);
for gg = 1:M
    % Frequencies of each row
    freqs(:, 1) = mp1(gg, [find(diff(mp1(gg, :))), end]);
    freqs(:, 2) = histc(mp1(gg, :), freqs(:, 1));
    cumfreqs = cumsum(freqs(:, 2));
    k = 1;
    for hh = 1:numel(freqs(:, 1))
      out1(gg, k:cumfreqs(hh)) = 1:freqs(hh, 2);
      out2(freqs(hh, 1), cumfreqs(hh)) = out2(freqs(hh, 1), cumfreqs(hh)) + freqs(hh, 2);
      k = cumfreqs(hh) + 1;
    end
end
toc
于 2013-10-25T22:54:05.480 回答
0

以下代码通过单个循环解决了第二个和第三个矩阵生成问题。为清楚起见,第二个矩阵M22-by-20示例中包含累积出现次数的数组。第三个矩阵M3是示例中大小的稀疏矩阵,10-by-20它编码每个唯一值最后一次出现的数量和位置。代码仅循环遍历行,accumarray用于完成大部分工作。mp1只要首先对行进行排序,它就可以推广到 的任何大小和内容。

% data
mp1 = [1 1 2 2 3 3 3 4 5 5 6 7 7 8 9 9 10 10 10 10;
       1 2 3 3 3 3 3 3 4 5 6 6 6 6 7 8 9  9  9  10]; % the example first matrix
nuniq = max(mp1(:));

% accumulate
M2 = zeros(size(mp1));
M3 = zeros(nuniq,size(mp1,2));

for ir=1:size(mp1,1),
    cumSums = accumarray(mp1(ir,:)',1:size(mp1,2),[],@numel,[],true)';
    segments = arrayfun(@(x)1:x,nonzeros(cumSums),'uni',false);
    M2(ir,:) = [segments{:}];
    countCoords = accumarray(mp1(ir,:)',1:size(mp1,2),[],@max,[],true);
    [ii,jj] = find(countCoords);
    nzinds = sub2ind(size(M3),ii,nonzeros(countCoords));
    M3(nzinds) = M3(nzinds) + nonzeros(cumSums);
end

我不会打印输出,因为它们对于答案来说有点大,并且代码可以按原样运行。

注意:对于新的测试数据,我建议使用 commands Mp = randi(10,[2,20]); mp1 = sort(Mp,2);。或者根据您对 user2875617 的请求和他的回复,确保所有数字都带有mp1 = sort([repmat(1:10,2,1) randi(10,[2,10])],2);但不是真正随机的......

编辑:代码中的错误已修复。

于 2013-10-26T03:33:57.933 回答
0

我相信以下代码可以满足您的要求。如果我不明白,你需要更清楚地提出你的问题......

注意 - 我硬编码了一些值/大小。显然,在“真实代码”中,您永远不会这样做。

% the bit of code that generates and sorts the initial matrix:
Mp = floor(1+(10*rand(2,20)));
mp1 = sort(Mp, 2);
clc
disp(mp1)

occCount = zeros(size(mp1));

for ii = 1:size(mp1,1)
    for jj = 1:size(mp1,2)
        if (jj == 1)
            occCount(ii,jj) = 1;
        else
            if (mp1(ii,jj) == mp1(ii,jj-1))
                occCount(ii,jj) = occCount(ii, jj-1) + 1;
            else
                occCount(ii,jj) = 1;
            end
        end
    end
end

% this is the second matrix you asked for
disp(occCount)

% now the third:
big = zeros(10, 20);
for ii = 1:size(mp1,1)
    for jj = 1:10
        f = find(mp1(ii,:) == jj); % index of all of them
        if numel(f) > 0
            last = f(end);
             n = numel(f);
             big(jj, last) = big(jj, last) + n;
        end
    end
end

disp(big)

请看看这是否确实是您的想法。

于 2013-10-25T22:08:40.340 回答