Pergunta

Alguém aqui sabe como excluir uma variável de um arquivo matlab?Eu sei que você pode adicionar variáveis ​​a um arquivo matlab existente usando o save -append método, mas não há documentação sobre como excluir variáveis ​​do arquivo.

Antes que alguém diga "é só salvar", é porque estou salvando etapas intermediárias de processamento em disco para aliviar problemas de memória, e no final haverá quase 10 GB de dados intermediários por rotina de análise.Obrigado!

Foi útil?

Solução

Curiosamente, você pode usar o -append opção com SALVAR para efetivamente apagar dados de um arquivo .mat.Observe este trecho da documentação (negrito adicionado por mim):

Para arquivos MAT, -append adiciona novas variáveis ​​ao arquivo ou substitui os valores salvos de variáveis ​​existentes por valores no espaço de trabalho.

Em outras palavras, se uma variável no seu arquivo .mat for chamada A, você pode salvar essa variável com um novo cópia de A (que você definiu para []) usando o -append opção.Ainda haverá uma variável chamada A no arquivo .mat, mas ele estará vazio e, portanto, reduzirá o tamanho total do arquivo.

Aqui está um exemplo:

>> 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

O tamanho do arquivo será de cerca de 7,21 MB.Agora faça isso:

>> 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

E agora o tamanho do arquivo será em torno de 169 bytes.A variável ainda está lá, mas está vazia.

Outras dicas

10 GB de dados?A atualização de arquivos MAT multivariáveis ​​pode ficar cara devido à sobrecarga do formato MAT.Considere dividir os dados e salvar cada variável em um arquivo MAT diferente, usando diretórios para organização, se necessário.Mesmo se você tivesse uma função conveniente para excluir variáveis ​​de um arquivo MAT, ela seria ineficiente.As variáveis ​​em um arquivo MAT são dispostas de forma contígua, portanto, a substituição de uma variável pode exigir a leitura e a gravação de grande parte do restante.Se estiverem em arquivos separados, você pode simplesmente excluir o arquivo inteiro, o que é rápido.

Para ver isso em ação, experimente este código, percorrendo-o no depurador enquanto usa algo como o Process Explorer (no Windows) para monitorar sua atividade de E/S.

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;

Na minha máquina, os resultados são assim.(Leitura e gravação são cumulativas, o tempo é por operação.)

                    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

Observe que atualizar a variável x pequena é mais caro do que atualizar a variável y grande.Grande parte dessa atividade de E/S é um trabalho de manutenção "redundante" para manter o formato de arquivo MAT organizado e desaparecerá se cada variável estiver em seu próprio arquivo.

Além disso, tente manter esses arquivos no sistema de arquivos local;será muito mais rápido que unidades de rede.Se eles precisarem ir para uma unidade de rede, considere fazer save() e load() em arquivos temporários locais (talvez escolhidos com tempname()) e depois copiá-los de/para a unidade de rede.O salvamento e o carregamento do Matlab tendem a ser muito mais rápidos com sistemas de arquivos locais, o suficiente para que o salvamento/carregamento local mais uma cópia possam ser um ganho líquido substancial.


Aqui está uma implementação básica que permitirá salvar variáveis ​​em arquivos separados usando as conhecidas assinaturas save() e load().Eles são prefixados com “d” para indicar que são versões baseadas em diretório.Eles usam alguns truques com evalin() e assignin(), então achei que valeria a pena postar o código completo.

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

Aqui está o equivalente a 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() é equivalente a whos('-arquivo').

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$', '');

E ddelete() para excluir as variáveis ​​individuais como você pediu.

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

A única maneira de fazer isso que conheço é usar a função API do arquivo MAT matDeleteVariable.Seria, eu acho, muito fácil escrever uma rotina Fortran ou C para fazer isso, mas parece muito esforço para algo que deveria ser muito mais fácil.

Sugiro que você carregue as variáveis ​​do arquivo .mat que deseja manter e salve-as em um novo arquivo .mat.Se necessário, você pode carregar e salvar (usando '-append') em um loop.

S = load(filename, '-mat', variablesYouWantToKeep);
save(newFilename,'-struct',S,variablesYouWantToKeep);
%# then you can delete the old file
delete(filename)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top