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

12

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

例如:

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

转换成

key = array([1,2])
我知道如何使用temp.keys()方法获取键。那么获取值也很容易,但如何将temp.keys()中的字符串列表强制转换为变量名而不是字符串呢?
我希望这样说起来有意义,但这可能非常简单,只是我无法想到如何做到。

1
你为什么想要这样做? - Patrick
我正在与一个使用Matlab的人合作。他们发送给我文件,当使用loadmat加载时,它是以字典格式呈现的。如果我能够编写一个快速执行上述操作的函数,那么暂时与它们一起工作并传递给我的函数将会更容易。我同意对于永久解决方案来说这并不重要,但目前这样做相当方便。由于通常只有5-15个键,每次都这样做会非常耗时。 - J Spen
2
你不可以直接保留字典并访问数组,而无需进行转换吗? - JoshAdel
@JoshAdel:是的,我可以这样做,但如果我能编写一个函数在ipython的交互式命名空间中执行上述操作会更容易。对于永久性解决方案,使用字典也不成问题。此外,我很好奇如何做到这一点,因为我想不出一个简洁/短的方法来实现它。 - J Spen
7个回答

12

在Python中,方法参数可以通过使用 ** 神奇符号作为字典传递:

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

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

my_func(**temp)

>>> array([1,2])

5
最好的方法是使用 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)))

虽然这不是最佳的代码实践,但在我测试的所有示例中都能很好地工作。


2
更好的方法可能是将数据存储到一个单独的对象中:
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不会尝试在本地变量中查找它。

1
关于locals()解决方案:如Python文档所述,“此字典的内容不应被修改”。 - Cédric Julien
啊,糟糕,没错——修改locals()只在某些情况下有效。 - pv.

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()的危险性的常规免责声明仍然适用,您应该仅在绝对信任的输入上运行此代码。

1

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

temp = {'key':[1,2]}

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

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


0

虽然我建议直接使用字典并像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

0
我有同样的问题,根据其他人的答案,我尝试了这段代码。在这里,我使用了pickle而不是Matlab来存储和检索数据。
保存数据:
x1=[2,4,6,8,10]
x2=[1,3,5,7,9]
x3='hello world'
vars={'x1':'x1','x2':'x2','x3':'x3'}

file='test.pickle'
f = open(file,'wb')
for key in vars.keys():
    pickle.dump(eval(vars[key]),f)

del x1,x2,x3

从文件中读取
s = open(file,'rb')
for k in vars:
    exec('{KEY} = {VALUE}'.format(KEY = k, VALUE = repr(pickle.load(s))))

print(x1,x2,x3)

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