16

ここの誰かがmatlabファイルから変数を削除する方法を知っていますか?メソッドを使用して既存のmatlabファイルに変数を追加できることは知っていますがsave -append、ファイルから変数を削除する方法に関するドキュメントはありません。

誰かが「それを保存するだけ」と言う前に、それはメモリの問題を軽減するために中間処理ステップをディスクに保存しているためです。最終的には、分析ルーチンごとにほぼ10GBの中間データがあります。ありがとう!

4

4 に答える 4

13

興味深いことに、SAVE-appendのオプションを使用して、.matファイルからデータを効果的に消去できます。ドキュメントからのこの抜粋に注意してください(私が太字で追加しました):

MATファイルの場合、ファイルに-append新しい変数を追加するか、既存の変数の保存された値をワークスペースの値に置き換えます

つまり、.matファイル内の変数が呼び出された場合、オプションを使用して、(設定した)の新しいコピーでAその変数を保存できます。.matファイルには引き続き変数が呼び出されますが、空であるため、ファイルの合計サイズが小さくなります。A[]-appendA

次に例を示します。

>> A = rand(1000);            %# Create a 1000-by-1000 matrix of random values
>> save('savetest.mat','A');  %# Save A to a file
>> whos -file savetest.mat    %# Look at the .mat file contents
  Name         Size                Bytes  Class     Attributes

  A         1000x1000            8000000  double

ファイルサイズは約7.21MBになります。今これを行います:

>> A = [];                              %# Set the variable A to empty
>> save('savetest.mat','A','-append');  %# Overwrite A in the file
>> whos -file savetest.mat              %# Look at the .mat file contents
  Name      Size            Bytes  Class     Attributes

  A         0x0                 0  double

そして今、ファイルサイズは約169バイトになります。変数はまだそこにありますが、空です。

于 2010-11-24T18:31:08.623 に答える
11

10 GBのデータ?多変数MATファイルの更新は、MAT形式のオーバーヘッドのためにコストがかかる可能性があります。データを分割し、必要に応じて整理用のディレクトリを使用して、各変数を別のMATファイルに保存することを検討してください。MATファイルから変数を削除する便利な関数があったとしても、それは非効率的です。MATファイル内の変数は連続して配置されるため、1つの変数を置き換えるには、残りの多くの読み取りと書き込みが必要になる場合があります。それらが別々のファイルにある場合は、ファイル全体を削除するだけで済みます。これは高速です。

これが実際に動作することを確認するには、このコードを試して、デバッガーでステップスルーしながら、Process Explorer(Windowsの場合)などを使用してI/Oアクティビティを監視します。

function replace_vars_in_matfile

x = 1;
% Random dummy data; zeros would compress really well and throw off results
y = randi(intmax('uint8')-1, 100*(2^20), 1, 'uint8');

tic; save test.mat x y; toc;
x = 2;
tic; save -append test.mat x; toc;
y = y + 1;
tic; save -append test.mat y; toc;

私のマシンでは、結果は次のようになります。(読み取りと書き込みは累積的であり、時間は操作ごとです。)

                    Read (MB)      Write (MB)       Time (sec)
before any write:   25             0
first write:        25             105              3.7
append x:           235            315              3.6
append y:           235            420              3.8

小さいx変数の更新は、大きいyの更新よりもコストがかかることに注意してください。このI/Oアクティビティの多くは、MATファイル形式を整理するための「冗長な」ハウスキーピング作業であり、各変数が独自のファイルにある場合はなくなります。

また、これらのファイルをローカルファイルシステムに保持するようにしてください。ネットワークドライブよりもはるかに高速になります。ネットワークドライブに移動する必要がある場合は、ローカルの一時ファイル(tempname()で選択される可能性があります)でsave()とload()を実行してから、ネットワークドライブとの間でコピーすることを検討してください。Matlabの保存と読み込みは、ローカルファイルシステムを使用するとはるかに高速になる傾向があるため、ローカルの保存/読み込みとコピーを追加することで、実質的な純利益を得ることができます。


これは、おなじみのsave()およびload()シグニチャを使用して変数を個別のファイルに保存できるようにする基本的な実装です。これらは、ディレクトリベースのバージョンであることを示すために「d」というプレフィックスが付いています。彼らはevalin()とassignin()でいくつかのトリックを使用しているので、完全なコードを投稿する価値があると思いました。

function dsave(file, varargin)
%DSAVE Like save, but each var in its own file
%
% dsave filename var1 var2 var3...
if nargin < 1 || isempty(file); file = 'matlab';  end
[tfStruct,loc] = ismember({'-struct'}, varargin);
args = varargin;
args(loc(tfStruct)) = [];
if ~all(cellfun(@isvarname, args))
    error('Invalid arguments. Usage: dsave filename <-struct> var1 var2 var3 ...');
end
if tfStruct
    structVarName = args{1};
    s = evalin('caller', structVarName);
else
    varNames = args;
    if isempty(args)
        w = evalin('caller','whos');
        varNames = { w.name };
    end
    captureExpr = ['struct(' ...
        join(',', cellfun(@(x){sprintf('''%s'',{%s}',x,x)}, varNames)) ')'];
    s = evalin('caller', captureExpr);
end

% Use Java checks to avoid partial path ambiguity
jFile = java.io.File(file);
if ~jFile.exists()
    ok = mkdir(file);
    if ~ok; 
        error('failed creating dsave dir %s', file);
    end
elseif ~jFile.isDirectory()
    error('Cannot save: destination exists but is not a dir: %s', file);
end
names = fieldnames(s);
for i = 1:numel(names)
    varFile = fullfile(file, [names{i} '.mat']);
    varStruct = struct(names{i}, {s.(names{i})});
    save(varFile, '-struct', 'varStruct');
end

function out = join(Glue, Strings)
Strings = cellstr(Strings);
if length( Strings ) == 0
    out = '';
elseif length( Strings ) == 1
    out = Strings{1};
else
    Glue = sprintf( Glue ); % Support escape sequences
    out = strcat( Strings(1:end-1), { Glue } );
    out = [ out{:} Strings{end} ];
end

これがload()に相当するものです。

function out = dload(file,varargin)
%DLOAD Like load, but each var in its own file
if nargin < 1 || isempty(file); file = 'matlab'; end
varNames = varargin;
if ~exist(file, 'dir')
    error('Not a dsave dir: %s', file);
end
if isempty(varNames)
    d = dir(file);
    varNames = regexprep(setdiff(ls(file), {'.','..'}), '\.mat$', '');
end

out = struct;
for i = 1:numel(varNames)
    name = varNames{i};
    tmp = load(fullfile(file, [name '.mat']));
    out.(name) = tmp.(name);
end

if nargout == 0
    for i = 1:numel(varNames)
        assignin('caller', varNames{i}, out.(varNames{i}));
    end
    clear out
end

Dwhos()はwhos('-file')と同等です。

function out = dwhos(file)
%DWHOS List variable names in a dsave dir
if nargin < 1 || isempty(file); file = 'matlab'; end
out = regexprep(setdiff(ls(file), {'.','..'}), '\.mat$', '');

そして、ddelete()を使用して、要求したように個々の変数を削除します。

function ddelete(file,varargin)
%DDELETE Delete variables from a dsave dir
if nargin < 1 || isempty(file); file = 'matlab'; end
varNames = varargin;
for i = 1:numel(varNames)
    delete(fullfile(file, [varNames{i} '.mat']));
end
于 2010-11-24T19:55:19.793 に答える
1

私が知っているこれを行う唯一の方法は、MATファイルAPI関数を使用することですmatDeleteVariable。これを行うためのFortranまたはCルーチンを作成するのは非常に簡単だと思いますが、もっと簡単なはずの何かのために多くの努力をしているように見えます。

于 2010-11-24T14:56:06.847 に答える
0

保持したい.matファイルから変数をロードし、それらを新しい.matファイルに保存することをお勧めします。必要に応じ'-append'て、ループで(を使用して)ロードおよび保存できます。

S = load(filename, '-mat', variablesYouWantToKeep);
save(newFilename,'-struct',S,variablesYouWantToKeep);
%# then you can delete the old file
delete(filename)
于 2010-11-24T15:42:52.153 に答える