-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 までのすべての数字を昇順で入力する必要があり、各数字の出現回数をカウントする 2 番目の行列は次のようになります。

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

先週から探していた最もトリッキーなマトリックスは、最初のマトリックスの各行をざっと調べて、各数値の出現回数と最後の出現位置を返す 3 番目のマトリックスです。コードがどのように機能するかの例。この例は、最初の行列の最初の行を実行した後の意図した結果を示しています。

    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

(数字)

この例は、最初の行列の 2 行目を実行した後の意図した結果を示しています。

    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

次のコードは、あなたが求めたすべてを実行すると思います。私が理解できなかった場合は、質問の仕方をもっと明確にする必要があります...

注 - 一部の値/サイズをハードコーディングしました。「実際のコード」では、明らかにそれを行うことはありません。

% 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 に答える
0

次のコードは、2 番目と 3 番目の行列生成の問題を 1 つのループで解決します。わかりやすくするために、2 番目の行列M22-by-20、累積発生回数を含む例の配列です。3 番目の行列は、各一意の値の最後の出現の数と位置をエンコードする例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

出力は答えには少し大きく、コードはそのまま実行できるため、出力は表示しません。

注: 新しいテスト データについては、コマンドを使用することをお勧めします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 に答える