これは私が以前に尋ねた質問に似ていますが、少し異なります。
そのため、matlab に非常に大きな構造体配列があります。議論のために、状況を単純化するために、次のようなものがあるとします。
structure(1).name, structure(2).name, structure(3).name structure(1).returns, structure(2).returns, structure(3).returns (実際のプログラムでは 647 個の構造体があります)
さらに、structure(i).returns がベクトル (非常に大きなベクトル、約 2,000,000 エントリ) であり、すべての i について structure(i).returns から j 番目のエントリを削除する条件が発生したとします。これどうやってやるの?というか、どうすればこれをかなり速く行うことができますか? 私はいくつかのことを試しましたが、それらはすべて非常に遅いです (すぐに説明します) ので、コミュニティがこれを行うためのより高速な方法を知っているかどうか疑問に思っていました.
データを 2 つの異なる方法で解析しました。最初の方法では、すべてがセル配列として保存されていましたが、うまく機能していなかったため、データを再度解析し、すべてをベクトルとして配置しました。
私が実際に行っているのは、NaN データと、データ ファイルの同じ対応する行にあるすべてのデータを削除しようとしていて、Hampel フィルターを適用した後にまったく同じことを行っていることです。この試みにおける私のコードの関連部分は次のとおりです。
for i=numStock+1:-1:1
for j=length(stock(i).return):-1:1
if(isnan(stock(i).return(j)))
for k=numStock+1:-1:1
stock(k).return(j) = [];
end
end
end
stock(i).return = sort(stock(i).return);
stock(i).returnLength = length(stock(i).return);
stock(i).medianReturn = median(stock(i).return);
stock(i).madReturn = mad(stock(i).return,1);
end;
for i=numStock:-1:1
for j = length(stock(i+1).volume):-1:1
if(isnan(stock(i+1).volume(j)))
for k=numStock:-1:1
stock(k+1).volume(j) = [];
end
end
end
stock(i+1).volume = sort(stock(i+1).volume);
stock(i+1).volumeLength = length(stock(i+1).volume);
stock(i+1).medianVolume = median(stock(i+1).volume);
stock(i+1).madVolume = mad(stock(i+1).volume,1);
end;
for i=numStock+1:-1:1
for j=stock(i).returnLength:-1:1
if (abs(stock(i).return(j) - stock(i).medianReturn) > 3*stock(i).madReturn)
for k=numStock+1:-1:1
stock(k).return(j) = [];
end
end;
end;
end;
for i=numStock:-1:1
for j=stock(i+1).volumeLength:-1:1
if (abs(stock(i+1).volume(j) - stock(i+1).medianVolume) > 3*stock(i+1).madVolume)
for k=numStock:-1:1
stock(k+1).volume(j) = [];
end
end;
end;
end;
ただし、これはエラーを返します。
「マトリックス インデックスは削除の範囲外です。
失敗のエラー (110 行目) stock(k).return(j) = [];"
その代わりに、すべてをベクトルとして解析してみました。次に、構造体配列を作成する前に、ベクター内の適切なエントリを削除してみることにしました。これはエラーを返しませんが、非常に遅いです:
%% Delete bad data, Hampel Filter
% Delete bad entries
id=strcmp(returns,'');
returns(id)=[];
volume(id)=[];
date(id)=[];
ticker(id)=[];
name(id)=[];
permno(id)=[];
sp500(id) = [];
id=strcmp(returns,'C');
returns(id)=[];
volume(id)=[];
date(id)=[];
ticker(id)=[];
name(id)=[];
permno(id)=[];
sp500(id) = [];
% Convert returns from string to double
returns=cellfun(@str2double,returns);
sp500=cellfun(@str2double,sp500);
% Delete all data for which a return is not a number
nanid=isnan(returns);
returns(nanid)=[];
volume(nanid)=[];
date(nanid)=[];
ticker(nanid)=[];
name(nanid)=[];
permno(nanid)=[];
% Delete all data for which a volume is not a number
nanid=isnan(volume);
returns(nanid)=[];
volume(nanid)=[];
date(nanid)=[];
ticker(nanid)=[];
name(nanid)=[];
permno(nanid)=[];
% Apply the Hampel filter, and delete all data corresponding to
% observations deleted by the filter.
medianReturn = median(returns);
madReturn = mad(returns,1);
for i=length(returns):-1:1
if (abs(returns(i) - medianReturn) > 3*madReturn)
returns(i) = [];
volume(i)=[];
date(i)=[];
ticker(i)=[];
name(i)=[];
permno(i)=[];
end;
end
medianVolume = median(volume);
madVolume = mad(volume,1);
for i=length(volume):-1:1
if (abs(volume(i) - medianVolume) > 3*madVolume)
returns(i) = [];
volume(i)=[];
date(i)=[];
ticker(i)=[];
name(i)=[];
permno(i)=[];
end;
end
私が言ったように、これは非常に遅いです。おそらく、非常に大きなデータ セットに対して for ループを使用しているためです。ただし、他にどのようにこれを行うかはわかりません。巨大な投稿で申し訳ありませんが、私が求めていることを合理的な方法で行う方法について誰か提案がありますか?
EDIT:ベクトルメソッドを機能させることがおそらく望ましいことを追加する必要があります。私の目的は、すべてのリターンベクトルをマトリックスに入れ、すべてのボリュームベクトルをマトリックスに入れ、それらに対してPCAを実行することです。セル配列を使用してそれを行う方法がわかりません(または、princompがセル配列で機能する場合でも)。
EDIT2:あなたの提案に合わせてコードを変更しました(ただし、このデータの再解析は時間的にはるかに悪いため、速度をあきらめて構造配列を維持するためにforループを維持することにしました)。新しいコード スニペットは次のとおりです。
stock_return = zeros(numStock+1,length(stock(1).return));
for i=1:numStock+1
for j=1:length(stock(i).return)
stock_return(i,j) = stock(i).return(j);
end
end
stock_return = stock_return(~any(isnan(stock_return)), : );
これにより、インデックスがマトリックスの次元を超えているというエラーが返されますが、その理由はわかりません。助言がありますか?