这里有人知道如何从 matlab 文件中删除变量吗?我知道您可以使用该save -append
方法将变量添加到现有的 matlab 文件中,但是没有关于如何从文件中删除变量的文档。
在有人说“直接保存”之前,这是因为我将中间处理步骤保存到磁盘以缓解内存问题,最终每个分析例程将有近 10 GB 的中间数据。谢谢!
有趣的是,您可以使用SAVE-append
选项有效地从.mat 文件中擦除数据。请注意文档中的这段摘录(我添加的粗体):
对于 MAT 文件,
-append
将新变量添加到文件或将现有变量的保存值替换为工作区中的值。
换句话说,如果您的 .mat 文件中的一个变量被调用,您可以使用该选项使用(您已设置为)的新副本A
保存该变量。.mat 文件中仍然会调用一个变量,但它会是空的,因此会减小文件的总大小。A
[]
-append
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 MB。现在这样做:
>> 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 字节。变量仍然在那里,但它是空的。
10 GB 数据?由于 MAT 格式开销,更新多变量 MAT 文件可能会变得昂贵。考虑拆分数据并将每个变量保存到不同的 MAT 文件中,必要时使用目录进行组织。即使您有一个方便的函数来从 MAT 文件中删除变量,它也是低效的。MAT 文件中的变量是连续布局的,因此替换一个变量可能需要读取和写入其余的大部分变量。如果它们在单独的文件中,您可以删除整个文件,这很快。
要查看实际情况,请尝试此代码,在调试器中单步执行它,同时使用 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
我知道的唯一方法是使用 MAT-file API function matDeleteVariable
。我想,编写一个 Fortran 或 C 例程来做到这一点会很容易,但是对于应该更容易的事情来说,这似乎需要付出很多努力。
我建议您从要保留的 .mat 文件中加载变量,并将它们保存到新的 .mat 文件中。如有必要,您可以循环加载和保存(使用'-append'
)。
S = load(filename, '-mat', variablesYouWantToKeep);
save(newFilename,'-struct',S,variablesYouWantToKeep);
%# then you can delete the old file
delete(filename)