2010-11-24 249 views
16

有没有人在这里知道如何删除变量从一个matlab文件?我知道您可以使用save -append方法将变量添加到现有的matlab文件,但没有关于如何从文件中删除变量的文档。因为我正在将中间处理步骤保存到磁盘以缓解内存问题,最终每个分析例程将会有近10 GB的中间数据。谢谢!从.mat文件中删除变量

回答

13

有趣的是,你可以从一个.MAT文件中使用-append选项与SAVE有效擦除数据。注意从文档的摘录(由我大胆的加入):

对于MAT文件,-append增加了新的变数文件或工作区的值替换现有变量保存的值。

换句话说,如果在你的.MAT文件中的变量称为A,可以节省超过,使用-appendA一个复印件(你已经设置为[])变量选项。 .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 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个字节左右。该变量仍然存在,但它是空的。

1

我所知道的唯一方法是使用MAT文件API函数matDeleteVariable。我想,编写一个Fortran或C例程来做这件事很容易,但是对于那些应该更容易的事情来说,它看起来像是一个很大的努力。

+0

哇,我希望这不是唯一的办法,但感谢指出。自从我用C语言写出任何东西之后,我已经有一段时间了...我一直试图写出你刚才提到的C例程。 – eykanal 2010-11-24 15:26:58

+0

@eykanal:我希望它不是唯一的方法。但是没有人告诉我们在命令窗口中执行此操作的更直接的方法。 – 2010-11-24 16:14:09

+2

可能有意不让这更方便。 MAT文件格式的连续布局意味着当你删除一个变量时,你需要将“垃圾”留在原地并浪费磁盘空间,或者可能重写大部分文件。有点像数组中某个元素的O(n)删除开销,但会花费磁盘I/O。公开一个deletevariable函数可能会导致不熟练的用户意外地执行大量不必要的I/O操作。 – 2010-11-24 20:05:58

0

我建议你从要保存的.mat文件中加载变量,并将它们保存到一个新的.mat文件中。如有必要,您可以在循环中加载并保存(使用'-append')。

S = load(filename, '-mat', variablesYouWantToKeep); 
save(newFilename,'-struct',S,variablesYouWantToKeep); 
%# then you can delete the old file 
delete(filename) 
+0

这就是我正在做的,但这是一个可行的解决方法。我真的很惊讶,似乎没有直接的方法来做到这一点。 – eykanal 2010-11-24 16:07:27

10

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变量大于更新大ý更昂贵。许多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