我想将numpy的array
的功能与本机python的dict
结合起来,即创建一个可以用字符串索引的多维数组。
例如,我可以这样做:
dict_2d = {'a': {'x': 1, 'y': 2},
'b': {'x': 3, 'y': 4}}
print dict_2d['a','y'] # returns 2
我知道我可以做dict_2d['a']['x']
但是长期来说我希望能够像numpy数组那样对待它们,包括进行矩阵乘法等等,并且不能用分层的dicts。
编写类的简单版本并不难,我只是使用类将所有字符串转换为int索引,然后使用numpy,但我想使用已存在的东西(如果可能的话)。 / p>
编辑:我不需要令人难以置信的表现。我将使用10x10阵列。我的目标是使代码编写简单而强大。使用numpy数组与在Fortran中编写它并没有太大的不同。我花了很多时间追踪Fortran索引错误...
答案 0 :(得分:9)
您可能正在寻找pandas,它提供了包装numpy数组的方便数据类型,允许您按名称而不是按数字访问行和列。
答案 1 :(得分:2)
我不喜欢给出现成的答案 - 但我认为用英语解释它会花费更多的时间 -
以numpy的方式获取对象的基本思想是自定义__getitem__
方法 - 以逗号分隔的值作为元组呈现给方法 - 你只需使用它中的值元组按顺序作为嵌套字典的索引。
除此之外,Python很容易使用collections.abc类创建功能完备的dict等效:如果在从collections[.abc].MutableMapping
进行调整时实现一组最小的方法,则模拟所有字典行为 - ({{1}然后,只需要正确迭代关键组件,并创建新的空的常规字典来存储所需的值。
__getitem__, __setitem__, __delitem__, __iter__, __len__
你准备好了:
try:
from collections import MutableMapping
except ImportError:
# Python3 compatible import
from collections.abc import MutableMapping
class NestedDict(MutableMapping):
def __init__(self, *args, **kw):
self.data = dict(*args, **kw)
def get_last_key_levels(self, key, create=False):
if not isinstance(key, tuple):
key = (key,)
current_data = self.data
for subkey in key:
previous = current_data
current_data = current_data[subkey] if not create else current_data.setdefault(subkey, {})
return previous, current_data, subkey
def __getitem__(self, key):
previous, current_data, lastkey = self.get_last_key_levels(key)
return current_data
def __setitem__(self, key, value):
previous, current_data, lastkey = self.get_last_key_levels(key, True)
previous[lastkey] = value
def __delitem__(self, key):
previous, current_data, lastkey = self.get_last_key_levels(key)
del previous[lastkey]
def __iter__(self):
return iter(self.data)
def __len__(self):
return len(self.data)
def __repr__(self):
return "NestedDict({})".format(repr(self.data))
请注意,这是一个高级实现,它可以正常工作,但是你将无法接近NumPy的优化级别 - 恰恰相反。如果您需要在这些对象中执行快速数据操作,您可以检查“cython” - 或者求助于将dict键转换为nuemric键并使用NumPy(这个想法仍然可以从这个答案中选择一些想法)< / p>
答案 2 :(得分:0)
使用熊猫 让我们说文件是这样的:
test.csv:
Params, Val1, Val2, Val3
Par1,23,58,412
Par2,56,45,123
Par3,47,89,984
所以你可以在python中做这样的事情:
import pandas as pd
x = pd.read_csv('test.csv', index_col='Params')
x['Val1']['Par3']
47