在不加载 .mat 文件的情况下检查变量是不是在 .mat 文件中的快速方法? 'who'/'whos' 并不比加载快.. 比 'who' 更好的选择?

Posted

技术标签:

【中文标题】在不加载 .mat 文件的情况下检查变量是不是在 .mat 文件中的快速方法? \'who\'/\'whos\' 并不比加载快.. 比 \'who\' 更好的选择?【英文标题】:Fast way to check if variable is in .mat file without loading .mat file? 'who'/'whos' is not faster than loading.. Better options than 'who'?在不加载 .mat 文件的情况下检查变量是否在 .mat 文件中的快速方法? 'who'/'whos' 并不比加载快.. 比 'who' 更好的选择? 【发布时间】:2018-01-08 13:50:29 【问题描述】:

我有一个名为“myfile.mat”的 .mat 文件,其中包含一个巨大的变量 data,在某些情况下,还有另一个变量 data_info。检查 .mat 文件是否包含 `data_info' 变量的最快方法是什么?

who 或 whos 命令并不比简单地加载和测试变量的存在更快。

nRuns=10;
%simply loading the complete file
tic
for p=1:nRuns
    load('myfile.mat');
    % do something with variable
    if exist('data_info','var')
        %do something
    end
end
toc

% check with who
tic
for p=1:nRuns
   variables=who('-file','myfile.mat');
   if ismember('data_info', variables)
       % do something
   end
end
toc

% check with whose
tic
for p=1:nRuns
   info=whos('-file','myfile.mat');
   if ismember('data_info', info.name)
       %do something
   end
end
toc

所有方法的时间大致相同(这很慢,因为data 很大。

但是,这非常快:

tic
for p=1:nRuns
    load('myfile.mat','data_info');
    if exist('data_info', 'var')
        %do something
    end
end
toc

但如果data_info 不存在,它会发出警告。我可以取消警告,但这似乎不是最好的方法。还有其他选择吗?

编辑 使用who('-file', 'myfile.mat', 'data_info') 也不是更快:

tic
for p=1:nRuns
    if ~isempty(who('-file', 'myfile.mat', 'data_info'))
      % do something
    end
end
toc    % this takes 7 seconds, roughly the same like simply loading complete .mat file

【问题讨论】:

matfile 也许? 请注意,对于正确的计时tic/toc 是不准确的;最好改用timeit @excaza:这比加载整个文件要好,但仍然不如whos/who。请参阅我的答案中的计时结果。 【参考方案1】:

尝试使用who 将其限制为仅特定变量:

...
if ~isempty(who('-file', 'myfile.mat', 'data_info'))
  %do something
end

定时解决方案:

在不同的解决方案上使用timeit(代码包含在下面,在Windows 7 和MATLAB 版本R2016b 上运行)表明基于who 的解决方案看起来最快,而我在上面建议的解决方案在速度上略有优势。以下是时间,从最慢到最快:

Load whole file:        0.368235871921381 sec
Using matfile:          0.001973860748417 sec
Load only `data_info`:  0.000316989486384 sec
Using whos + ismember:  0.000174207817967 sec
Using who + ismember:   0.000151289605527 sec
Using who + isempty:    0.000137261391331 sec

我使用了一个包含以下变量的示例 MAT 文件:

data = ones(10000);
data_info = 'hello';

这是测试代码:

function T = infotest

  T = zeros(6, 1);
  T(1) = timeit(@use_load_exist_1);
  T(2) = timeit(@use_load_exist_2);
  T(3) = timeit(@use_matfile);
  T(4) = timeit(@use_whos_ismember);
  T(5) = timeit(@use_who_ismember);
  T(6) = timeit(@use_who_isempty);

end

function isThere = use_load_exist_1
  load('infotest.mat');
  isThere = exist('data_info', 'var');
end

function isThere = use_load_exist_2
  load('infotest.mat', 'data_info');
  isThere = exist('data_info', 'var');
end

function isThere = use_matfile
  isThere = isprop(matfile('infotest.mat'), 'data_info');
end

function isThere = use_whos_ismember
  info = whos('-file', 'infotest.mat');
  isThere = ismember('data_info', info.name);
end

function isThere = use_who_ismember
  variables = who('-file', 'infotest.mat');
  isThere = ismember('data_info', variables);
end

function isThere = use_who_isempty
  isThere = ~isempty(who('-file', 'infotest.mat', 'data_info'));
end

【讨论】:

不,这并不比简单地加载完整的 .mat 文件快。 @AntonRodenhauser:你是如何衡量的? timeittic/toc 更准确。 在所有情况下大约需要 7 秒.. 即使 timeit 更准确一点 - 我认为它不会有太大的不同? @AntonRodenhauser:使用timeit 我发现使用whos/who 和加载数据(尤其是加载所有数据)之间存在显着差异。您使用的是哪个版本的 MATLAB?【参考方案2】:

你可以使用who命令https://www.mathworks.com/help/matlab/ref/who.html

此语法是调用who,带有文件的指示符,然后是您要查找的变量。您不需要查找文件中的所有变量

虚拟语法如下

variable = who('-file','yourfilenamehere','data_info')

从那里你可以打电话

if ~isempty(variable)
%do something
end

这仅在文件中搜索该变量。在您的who 命令版本中,您查找所有变量,而这只是查找一个。

【讨论】:

不,这并不比加载完整的 .mat 文件快【参考方案3】:

所以它有点乱,但我只是尝试过这个,它几乎是即时的,不管大小。让我知道它是否适合你。

请原谅格式,我不习惯这里的正确格式。

注意:此解决方案使用已内置于 matlab 中的低级 HDF5 库,因此此方法假定您的 mat 文件是 HDF5 (-v7.3)。否则将无法正常工作。

您可以通过这样做确定是一个有效的 hdf5 文件:

isValidHDF = H5F.is_hdf5('my_file.mat');

查看你的变量是否存在:

isThere = false; %Initialize as default value of false
fid = H5F.open('myfile.mat') % Use low level H5F builtin to open
try % Never use try/catch but this is a good for when its ok
     % Try to open the h5 group. Will error and catch to report back false if the variable isnt there, otherwise the variable exists
     gid = H5G.open(fid,['/data_info']); % Note: the "/" is required and OS independent, so its never "\" even in windows

     % I think this makes sure the variable isnt empty if the group opened successfully, but it hasnt been a problem yet
     hInfo = H5G.get_info(gid); 
     isThere = hInfo.nlinks > 0;
     H5G.close(gid);
end
H5F.close(fid);

【讨论】:

自从我写了这个答案以来,我现在对这些库有了更多的了解。与 H5G.open (group) 相反,使用 H5L.open (link) 可能会更好。它将识别嵌套组或嵌套数据集的存在,并且似乎被认为是更好的做法。 H5 库方法还有助于嵌套/递归结构,例如检查存储在 .mat 文件中的嵌套变量“a.b.c.d”是否存在

以上是关于在不加载 .mat 文件的情况下检查变量是不是在 .mat 文件中的快速方法? 'who'/'whos' 并不比加载快.. 比 'who' 更好的选择?的主要内容,如果未能解决你的问题,请参考以下文章

如何加载对我的机器来说内存太大的 .mat 文件的一部分?

如何在不检查路径扩展名的情况下检查文件是不是为图像文件?

如何在不使用 MATLAB 的情况下打开 .mat 文件?

如何在不下载的情况下使用其 URL 检查文件是不是存在?

在 PHP 中是不是可以在不先提取其内容的情况下检查 Zip 文件的内容?

在不移动文件指针的情况下检查文件指针是不是已达到 EOF?