2

データセットで毎年最大値を取得しようとしています。データは 1 列に、毎日のタイムステップで順番に表示されます。最初の 365 行から最大値を取得し、次に次の 365 行から最大値を取得するにはどうすればよいですか? 私は次のようなことを考えていました:

years=31;
for i=1:years
peak(i)=max(data(i:365*i,2))
end

ただし、i=2 の場合、範囲は 366:730 などになります。データ マトリックスは 11322x7 double で、列 2 が必要です。

4

2 に答える 2

2

@Thiloの答えのようなものを提案することを考えましたが、うるう年は考慮されていません(365 * 31 = 11315で11322未満であるため、データに表示されるようです)

複雑なベクトル化されたソリューションを作成できるかもしれませんが、開始インデックスと停止インデックスを手動で追跡したくなるでしょう。

NYEARS = 31;

start = 1;
stop = 365 + isLeapYear(year(1));
n=1;
maxValues = nan(NYEARS,1);
while(n=<NYEARS)
  maxValues(n) = max(data(start:stop,2));
  n=n+1;
  start = stop + 1;
  stop = start + 365 + isLeapYear(year(n));
end

おそらく猛烈に速いわけではありませんが、これがボトルネックになるとは思えません。

function leap_p = isLeapYear(year)
  leap_p = ~mod(year,400) || (~mod(year,4) && mod(year,100)) 
end
于 2012-05-06T05:36:14.017 に答える
1

うるう年を含む更新

あなたが持っているデータの量にとってそれが問題になるとは思えませんが、うるう年を含め、ループを使用しない解決策を思いついたと思います. したがって、完全を期すために。うるう年が 11 日、通常の年が 10 日であるミニ例を使用して、アイデアを再度構築します。

data = 1:103
isLeapYear = [false, false, true, false, false, true, false, false, true, false]

そのベクトルは、すべての年の isLeapYear 関数の結果に置き換える必要があります。

次に、値 1 のみを含む、11 (実際には 366) 行と年数列を含む行列を生成します。

helpmatrix = ones(11, 10)

対応する年がうるう年でない場合は、行列の最後の行を 0 に設定します。

helpmatrix(end, ~isLeapYear) = 0

行列をベクトルとして書き(以下で説明するように reshape を使用)、すべてのものを合計しましょう

selector = cumsum(reshape(helpmatrix, prod(size(helpmatrix)), 1))

これらの値を使用して、元のデータを、毎年 11 (366) 日となるように膨らませることができます。以下のトリックを使用できます。11 日目の値を埋めるために、10 日目の値を再利用するだけです。これにより、最大値も最小値も変更されません。(ただし、注意してください: 他の機能もこれによって影響を受ける可能性があります!)

max(reshape(data(selector), 11, length(selector)/11))

これを変換するには、すべての 10 と 11 を 365 と 366 で交換し、data(selector, 2)代わりに を使用して最後のコマンドを変更するだけですdata(selector)

おそらくこれは、ループ ソリューションと比較して大きな利点ではありませんが、ベクトル計算の能力を示しています。


古い提案

はるかに簡単な方法でそれを行うことができます。

この関数reshapeを使用すると、ベクトル (または必要に応じて行列) を別の行/列レイアウトに変換できます。

あなたの問題は、次の方法で解決できます

max(reshape(data(:,2), 365, length(data)/365))

何が起こっているのかを理解するために、より小さな例を作成しました。

data = 1:100
reshape(data, 10, length(data)/10)
max(reshape(data', 10, length(data')/10))

上記のループも機能しますが、非効率的です。インデックスの作成方法に注意する必要があります。あなたはそうしますi:365*i。上記の私の例では、これは次のようになります

for i=1:10
    i:10*i
end

これは明らかにあなたが望むものではありません。あなたができる正しい方法で行った

for i=1:10
    (10*(i-1) + 1):10*i
end

それが役立つことを願っています。

于 2012-05-06T05:27:52.157 に答える