11

MATLAB を使用して、行列のすべての列に関数を適用したいと考えています。たとえば、スムーズに行列をベクトルとして扱うのではなく、行列のすべての列でスムーズを呼び出せるようにしたいと思います (これは、を呼び出す場合のデフォルトの動作ですsmooth(matrix))。

これを行うにはもっと慣用的な方法があるに違いないと確信していますが、それが見つからないため、map_column関数を定義しました。

function result = map_column(m, func)
    result = m;
    for col = 1:size(m,2)
        result(:,col) = func(m(:,col));
    end
end

私が呼び出すことができる:

smoothed = map_column(input, @(c) (smooth(c, 9)));

このコードに何か問題がありますか? どうすれば改善できますか?

4

6 に答える 6

10

MATLABの「for」ステートメントは、実際には提供されたものの列をループします。通常、forに渡されるベクトル(上記の例のように)は行ベクトルであるため、これはスカラーのシーケンスになります。これは、上記のコードを次のように書き直すことができることを意味します。

function result = map_column(m, func)
    result = [];
    for m_col = m
      result = horzcat(result, func(m_col));
    end

funcが列ベクトルを返さない場合は、次のようなものを追加できます。

f = func(m_col);
result = horzcat(result, f(:));

それを強制的に列に入れます。

于 2008-10-23T18:17:14.143 に答える
3

あなたの解決策は大丈夫です。

horizcatは、大きな行列に対してかなりのパフォーマンスペナルティを課すことに注意してください。これにより、コードはO(N)ではなくO(N ^ 2)になります。100x10,000のマトリックスの場合、私のマシンでは実装に2.6秒かかり、horizcatの実装には64.5秒かかります。100x5000マトリックスの場合、horizcatの実装には15.7秒かかります。

必要に応じて、関数を少し一般化して、最終的なディメンションまたは任意のディメンション(列だけでなく)を反復処理できるようにすることができます。

于 2008-11-09T07:30:35.883 に答える
2

おそらく、常に行列を ' 演算子で変換してから、結果を元に戻すことができます。

smoothed = smooth(input', 9)';

これは、少なくとも fft 関数で機能します。

于 2008-10-19T15:05:52.753 に答える
2

行列の列全体で暗黙的なループを発生させる方法は、cellfun を使用することです。つまり、最初に行列をセル配列に変換する必要があります。各セルは 1 つの列を保持します。次に、cellfun を呼び出します。例えば:

A = randn(10,5);

ここで、各列の標準偏差を計算したことを確認してください。

cellfun(@std,mat2cell(A,size(A,1),ones(1,size(A,2))))

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

もちろん、MATLAB の多くの関数は、ユーザーが指定したように、配列の行または列で動作するように既に設定されています。これはもちろんstdにも当てはまりますが、これはcellfun正常に機能したことをテストするための便利な方法です。

std(A,[],1)

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482
于 2009-04-11T02:34:02.390 に答える
1

大きな行列を扱う場合は、結果の行列を事前に割り当てることを忘れないでください。そうしないと、CPU が新しい行/列を追加するたびに、行列を繰り返し再割り当てするために多くのサイクルを費やすことになります。

于 2008-12-10T18:11:21.013 に答える
0

これが関数の一般的なユースケースである場合、入力がベクトルでない場合は、関数が列を自動的に反復するようにすることをお勧めします。

これは問題を正確に解決するわけではありませんが、関数の使用法を単純化するでしょう。その場合、出力も行列である必要があります。

を使用して、行列を1つの長い列に変換することもできますm(:,:) = m(:)。ただし、これが理にかなっているかどうかは、関数によって異なります。

于 2008-10-19T14:15:31.310 に答える