使用 scipy.io.loadmat 从 .mat Matlab 文件中将字典键转换为 Python 中具有相同值的变量名

Posted

技术标签:

【中文标题】使用 scipy.io.loadmat 从 .mat Matlab 文件中将字典键转换为 Python 中具有相同值的变量名【英文标题】:Turn the dictionary keys into variable names with same values in Python from .mat Matlab files using scipy.io.loadmat 【发布时间】:2011-09-16 04:57:16 【问题描述】:

我正在尝试使用 scipy.io.loadmat 从 .mat 文件加载基本字典 temp = 'key':array([1,2])。将 loadmat() 返回的 Python 字典文件中的键转换为与表示键值相同的变量名。

例如:

temp = 'key':array([1,2])

变成了

key = array([1,2])

我知道如何使用 temp.keys() 获取密钥。然后抓取项目很容易,但我如何强制 temp.keys() 中的字符串列表为变量名而不是字符串。

我希望这是有道理的,但这可能真的很容易,我只是想不出该怎么做。

干杯

【问题讨论】:

你为什么要这样做? 我正在与使用 Matlab 的人合作。他们向我发送文件,这些文件在加载 loadmat 时采用字典格式。如果我可以编写一个函数来快速完成上述工作,那么临时使用它们并将传递给我的函数会更容易。我同意永久解决方案无关紧要,但目前弄乱它会相当方便。由于它通常是 5-15 个键,因此每次执行都会相当耗时。 难道您不能像temp['key'] 那样轻松地保留字典并直接访问数组而不进行转换吗? @JoshAdel:是的,我可以这样做,但如果我可以编写一个函数来执行上述操作,那么在 ipython 的交互式名称空间中会更容易。对于永久解决方案,字典不是问题。我也很好奇如何做到这一点,因为我想不出一个简洁/简短的方法来做到这一点。 【参考方案1】:

上面的答案都不适用于 numpy 数组和其他非内置类型。但是,以下操作:

import numpy as np
temp = 'a':np.array([1,2]), 'b': 4.3, 'c': 'foo', 'd':np.matrix([2,2])
for var in temp.keys():
    exec(" = temp['']".format(var, var))

注意引号的顺序。这允许 var 在第一个实例中被视为一个变量,然后在第二个实例中被视为一个键,索引到 temp 字典中。

当然,关于exec()eval() 的危险的常见免责声明仍然适用,您应该只在您绝对信任的输入上运行。

【讨论】:

【参考方案2】:

使用 exec() 更简单,正如 hdhagman 回答的那样。我写了更简单的代码。

temp = 'key':[1,2]

for k, v in temp.items():
    exec("%s = %s" % (k, v))

打印(键) => [1,2]

【讨论】:

【参考方案3】:

最好的办法是使用temp['key']。但是,要回答这个问题,您可以使用 exec 函数。这样做的好处是您可以这样做,而不必硬编码任何变量名或将自己限制在函数内部。

from numpy import array,matrix

temp = 'key':array([1,2]),'b': 4.3,'c': 'foo','d':matrix([2,2])

for k in temp:
    exec('KEY = VALUE'.format(KEY = k, VALUE = repr(temp[k])))

>>> key
array([1, 2])
>>> b
4.3
>>> c
'foo'
>>> d
matrix([[2, 2]])

注意:这仅在您从模块中导入特定功能时才有效。如果您因为代码实践或需要导入的大量函数而不想这样做,您可以编写一个函数来连接条目前面的模块名称。输出与上例相同。

import numpy as np,numpy

temp = 'key':np.array([1,2]),'b': 4.3,'c': 'foo','d':np.matrix([2,2])

def exec_str(key,mydict):
    s = str(type(mydict[key]))
    if '.' in s:
        start = s.index("'") + 1
        end = s.index(".") + 1
        v = s[start:end:] + repr(mydict[key])
    else:
        v = repr(mydict[key])     
    return v

for k in temp:
    exec('KEY = VALUE'.format(KEY = k, VALUE = exec_str(k,temp)))

虽然这不是最佳代码实践,但它适用于我测试的所有示例。

【讨论】:

【参考方案4】:

更好的方法可能是将数据填充到单独的对象中:

class attrdict(dict):
    def __getattr__(self, k): return self[k]
    def __setattr__(self, k, v): self[k] = v

somedict = 'key': 123, 'stuff': 456

data = attrdict(somedict)
print data.key
print data.stuff

这与交互使用一样容易,并且不需要任何魔法。 这对 Matlab 用户来说也应该没问题。

编辑:事实证明,下面的内容大部分时间都不起作用。太糟糕了,魔法就这么多。

如果你想玩魔法,你可以做类似的事情

locals().update(somedict)

这将在交互中正常工作,您甚至可以通过弄乱sys._getframe().f_back.f_locals 在加载器函数中隐藏对locals() 的访问。

但是,这在函数中不起作用:

def foo():
    locals().update('a': 4)
    print a 

关键是上面的a在编译时绑定到全局变量,因此Python不会尝试在局部变量中查找它。

【讨论】:

关于 locals() 解决方案:如python documentation、The contents of this dictionary should not be modified 中所述 啊,废话,没错——修改 locals() 仅在某些情况下有效。【参考方案5】:

虽然我只建议直接使用字典并访问像 temp['key'] 这样的数组,但如果您提前知道所有变量名称,您可以编写一个函数将它们提取到单个变量中:

def func(**kwargs):
    return kwargs['a'],kwargs['b']


temp = 'a':np.array([1,2]),'b':np.array([3,4])
a,b = func(**temp)
del temp # get rid of temporary dict

【讨论】:

【参考方案6】:

在python中,方法参数可以通过**魔法作为字典传递:

def my_func(key=None):
   print key
   #do the real stuff

temp = 'key':array([1,2])

my_func(**temp)

>>> array([1,2])

【讨论】:

以上是关于使用 scipy.io.loadmat 从 .mat Matlab 文件中将字典键转换为 Python 中具有相同值的变量名的主要内容,如果未能解决你的问题,请参考以下文章

使用 scipy.io.loadmat 在 python 中加载 matlab 表

Scipy IO Loadmat 错误:ValueError:Mat 4 mopt 格式错误

scipy.io.loadmat 嵌套结构(即字典)

使用 scipy.io loadmat 将 Matlab 结构导入 python 时的值错误

如何使用 Scipy.io.loadmat 将 Matlab mat 文件中的字符串单元格数组加载到 Python 列表或元组中

在 python 中访问包含 matlab 类的 .mat 文件