2012-03-09 15 views
1

私は次の行列があると:マトリクスシングルライナーのMatlab検索置換?

1 0 1 1 0 0 
0 0 1 0 1 0 
1 1 1 0 0 1 
0 1 1 0 0 1 
1 1 1 1 1 0 

それは以下になるので、私は、その列インデックスによって各列の各1を交換異なる形式に変換する:

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

私はそれを「ダム」の方法行うことができます。

[H, W] = size(a); 
for i = 1:H 
    for j = 1:W 
     if(a(i, j) == 1) 
      a(i, j) = j; 
     end 
    end 
end 

をしかし、確かに(おそらく「検索」機能を使用して)1行でそれを行う方法がなければならない、誰K今どのように?

答えて

3

これはスーパーの一般的なものではありませんが、あなたがしたいものです。 find返すデータの1次元バージョンのインデックスので、我々は2-Dのバージョンを取得するには少し算術演算を実行する必要があります。

a(a == 1) = floor((find(a == 1) - 1)/size(a, 1)) + 1 

あなたが代わりに行インデックスをやってみたかった場合、あなたは

を使用することができます
a(a == 1) = mod(find(a == 1) - 1, size(a, 1)) + 1 

あなたは大きな行列でこれをやっていた場合は、まず一時変数にfind(a == 1)を割り当てることができますが:

inds = find(a == 1) 
a(inds) = floor((inds - 1)/size(a, 1)) + 1 

は(目に注意してください。 aにインデックスするか、またはブール値の行列を使用して同じことを行います)。

元の行列が0と1だけであることがわかっている場合は、find(a)を使用することもできます。

これは手動で基本的には@tmpearce's answerが行うことです。

+0

答えをいただきありがとうございます、これは有望ですが、正しく動作しません。最後の行は、1つのインデクシングストライク@Griffinおっと、1 – Griffin

+0

によってオフセットされています!私はそれを説明するために私の答えを修正しました。 – Dougal

0

私はmatlabを使用して以来、長い時間がかかりましたので、私の頭の中からあなたにコードを渡すことはできません。しかし、ここで私はそれを行う方法です:

ベクトル1:columsを作成し、repmatを使用して行ごとに1回繰り返してから、この要素ごとに元の行列を掛けます。

また、ループはmatlabでは遅いので、行列演算は高速ですが、そのような1つのライナーはおそらく現在のコードよりはるかに高速です。

3

あなたは行列a

[r,c]=ind2sub(size(a),find(a)); 
a(find(a))=c; 

編集があります。それはあなたにとって重要なので、これは、1行でなんとかです:

[r,a(find(a))]=ind2sub(size(a),find(a)); 
+0

ありがとう、私はそれが最も計算効率の良い方法だと確信していますが、私はオンライナーを探していました。とにかく+1。 – Griffin

+0

@griffin私はちょうど編集しました。これは1行で動作しますが、分かりやすくするために2つありました。 – tmpearce

2

あなたがこれを行うにはmeshgridを使用することができます。

[H, W] = size(a); 
a = a.*meshgrid(1:H,1:W); 
+0

+1にお返事いただき、ありがとうございました – Griffin

+1

@グリフィン:どうぞよろしくお願いいたします。 'a'の2つのコピーを保持するのに十分なRAMがあれば、' meshgrid'の解決策は 'find'より速くなければなりません(確かめるためにプロファイラを実行したいかもしれませんが) – Jonas