将Matlab中的.mat文件加载到变量中

7

当直接从.Mat文件中将数据加载到变量中时,它会存储一个结构体而不是变量本身。

例如:

myData.mat 包含 var1var2var3

如果我执行以下操作:

load myData.mat

它将在我的工作空间中创建var1、var2和var3变量。好的。

如果我将load返回的内容赋值给一个变量,它会存储一个结构体。这是正常的,因为我正在加载多个变量。

foo = load('myData.mat')

foo = 
  struct with fields:
    var1
    var2
    var3

然而,假设我只对var1感兴趣,并且想直接存储到一个名为foo的变量中。

Load有一个选项可以从.mat文件中仅加载特定变量,但它仍然会存储一个结构体。

foo = load('myData.mat', 'var1')
foo = 
      struct with fields:
        var1

我希望var1直接赋值给foo

当然,我可以这样做:

foo = load('myData.mat', 'var1')
foo = foo.var1;

但是应该有一种自动化的方法可以在一行代码中实现,对吧?

什么困扰了你?是 clear var1 吗?如果是这样,你可以使用:foo=load('myData.mat', 'var1'),然后再使用 foo=foo.var1; - Sardar Usama
让我困扰的是我不能直接加载我想要的变量,而必须将foo重新分配给foo.var1。我会更新问题并采纳您的建议,这比使用clear更好。Matlab应该有一个特殊情况,当您仅加载一个变量时,它不会加载结构体。 - user2261062
4个回答

3
如果MAT文件只包含一个变量,使用:
x = importdata(mat_file_name)

1

@Suever是正确的,但如果你想要一个一行代码的解决方法,这个可以达到目的:

foo = getfield(load('myData.mat'), 'var1');

1
自R2020a版本开始,可以使用foo = load(...).var1进行操作。https://www.mathworks.com/help/matlab/matlab_prog/indexing-into-function-call-results.html - Cris Luengo

1
load 在其他情况下不会表现出这种行为,否则 load 将根据您请求的变量数量而表现不一致,这将导致极其混乱的行为。
举个例子,假设您编写了一个通用程序,想要从 .mat 文件中加载所有变量,对它们进行一些修改,然后再次保存。您希望此程序可以处理 任何 文件,因此某些文件可能仅包含一个变量,而另一些文件可能存储多个变量。
如果 load 使用您指定的行为,那么在加载和修改文件之前,您必须添加各种逻辑来检查文件中存储了多少个变量。
以下是使用当前的 load 行为的程序示例:
function modifymyfile(filename)
    data = load(filename);

    fields = fieldnames(data);

    for k = 1:numel(fields)
        data.(fields{k}) = modify(data.(fields{k}));
    end

    save(filename, '-struct', 'data')
end

如果行为是你认为你想要的方式
function modifymyfile(filename)

    % Use a matfile to determine the number of variables
    vars = whos(matfile(filename));

    % If there is only one variable
    if numel(vars) == 1
        % Assign that variable (have to use eval)
        tmp = load(filename, vars(1).name);
        tmp = modify(tmp);

        % Now to save it again, you have to use eval to reassign
        eval([vars(1).name, '= tmp;']);

        % Now resave
        save(filename, vars(1).name);
    else
        data = load(filename);

        fields = fieldnames(data);

        for k = 1:numel(fields)
            data.(fields{k}) = modify(data.(fields{k}));
        end

        save(filename, '-struct', 'data');
    end
end

我会留给读者决定哪一个更易读和更健壮。
最好的方法就是按照你在问题中展示的方式,在加载后重新分配值。
data = load('myfile.mat', 'var1');
data = data.var1;

更新

即使您只希望在变量被明确指定时不将其分配给struct,您仍将面临不一致的行为,这将使如果我的程序接受要更改的变量列表作为单元数组变得困难。

variables = {'var1', 'var2'}

data = load(filename, variables{:});    % Would yield a struct

variables = {'var1'};

data = load(filename, variables{:});    % Would not yield a struct

1
我认为,如果您只调用load而不指定要加载哪些变量,则即使mat文件只有一个变量,也必须返回一个结构体。但是,如果您明确传递变量列表并且只传递一个变量,则我认为直接加载变量是可以接受的。或者让load接受一个标志,以便直接通过结构体获取变量。 - user2261062
@SembeiNorimaki 第一个示例仍将产生不一致的行为。标志是更好的方法,但它确实会给load增加不必要的复杂性,因为您可以在调用函数中用一行代码做相同的事情。 - Suever

0

它看起来很丑,但能实现你想要的功能:

foo = subsref(matfile('myData.mat'),struct('type','.','subs','var1'))

使用 matfile 可以部分加载变量到内存中,即只加载必要的内容。在这种情况下,函数 subsref 执行索引运算符“。”的作用。


注意:要使用matfile,您必须使用v7.3压缩保存.mat文件:save('myData.mat','var1','var2','-v7.3') - Tu Bui

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接