Удаление переменных из файла .mat
Кто-нибудь знает, как удалить переменную из файла matlab? Я знаю, что вы можете добавлять переменные в существующий файл matlab с помощью метода save -append
, но нет документации о том, как удалить переменные из файла.
Прежде чем кто-нибудь скажет "просто сохраните его", это потому, что я сохраняю промежуточные этапы обработки на диске, чтобы облегчить проблемы с памятью, и в конце будет около 10 ГБ промежуточных данных для каждой процедуры анализа. Спасибо!
Ответы
Ответ 1
Интересно, что вы можете использовать опцию -append
с SAVE, чтобы эффективно стереть данные из файла .mat. Обратите внимание на этот отрывок из документации (жирный текст добавлен мной):
Для MAT файлов -append
добавляет новые переменные в файл или заменяет сохраненные значения существующих переменных значениями в рабочей области.
Другими словами, если переменная в вашем .mat файле называется A
, вы можете сохранить эту переменную с новой копией A
(которую вы установили на []
) с помощью -append
. В файле .mat все еще будет переменная A
, но она будет пустой и, следовательно, уменьшит общий размер файла.
Вот пример:
>> 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,21 МБ. Теперь сделайте следующее:
>> 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 байт. Переменная все еще там, но она пуста.
Ответ 2
10 ГБ данных? Обновление многовариантных файлов MAT может стать дорогостоящим из-за накладных расходов формата MAT. Рассмотрите разделение данных и сохранение каждой переменной в другой файл MAT, используя каталоги для организации, если это необходимо. Даже если у вас была удобная функция для удаления переменных из файла MAT, это было бы неэффективно. Переменные в файле MAT сложены, поэтому замена одной переменной может потребовать много чтения и записи. Если они находятся в отдельных файлах, вы можете просто удалить весь файл, который быстро.
Чтобы увидеть это в действии, попробуйте этот код, пройдя через него в отладчике, используя что-то вроде Process Explorer (в Windows), чтобы отслеживать его активность ввода-вывода.
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. Большая часть этой операции ввода-вывода является "избыточной" работой по ведению домашнего хозяйства, чтобы сохранить формат файла MAT и уйти, если каждая переменная находится в собственном файле.
Кроме того, попробуйте сохранить эти файлы в локальной файловой системе; это будет намного быстрее, чем сетевые диски. Если им нужно перейти на сетевой диск, подумайте о том, чтобы делать save() и load() в локальных файлах temp (возможно, выбрано с помощью tempname()), а затем копировать их в/из сетевого диска. Сохранение и загрузка 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
Ответ 3
Единственный способ сделать это, который я знаю, - использовать функцию API MAT файла matDeleteVariable
. По-моему, было бы довольно легко написать программу Fortran или C, чтобы сделать это, но это похоже на много усилий для чего-то, что должно быть намного проще.
Ответ 4
Я предлагаю вам загрузить переменные из файла .mat, которые вы хотите сохранить, и сохранить их в новый файл .mat. При необходимости вы можете загружать и сохранять (используя '-append'
) в цикле.
S = load(filename, '-mat', variablesYouWantToKeep);
save(newFilename,'-struct',S,variablesYouWantToKeep);
%# then you can delete the old file
delete(filename)