Python如何用字符串键索引多维数组,如字典
Posted
技术标签:
【中文标题】Python如何用字符串键索引多维数组,如字典【英文标题】:Python how to index multidimensional array with string key, like a dict 【发布时间】:2015-07-23 19:19:30 【问题描述】:我想将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,但如果可能的话,我想使用已经存在的东西。
编辑:我不需要令人难以置信的表现。我将使用 10x10 数组。我的目标是让编写代码变得简单而健壮。使用 numpy 数组与仅在 Fortran 中编写它并没有太大的不同。我已经花费了足够多的时间来追踪 Fortran 索引错误...
【问题讨论】:
您真的需要将数据存储在嵌套结构中吗?你可以只使用一个键是元组的字典。 @BrenBarn 可能会使用 大量 内存 你想通过不使用 numpy 来实现什么?如果您只想要行/列的字符串标签,请查看pandas,它提供了很好的表格数据类型,可以包装 numpy 数组。 @BrenBarn 我根本不想避免 numpy。它似乎并没有自己做字符串标签。 pandas 看起来就像我希望的那样。我会更详细地检查一下 @BrenBarn Pandas 正是我想要的。如果你想把它写成答案,我会接受。 【参考方案1】:您可能正在寻找 pandas,它提供了包装 numpy 数组的便捷数据类型,允许您按名称而不是仅按数字访问行和列。
【讨论】:
【参考方案2】:我不喜欢给出现成的答案 - 但我认为用英语解释它需要更多时间 -
fetch 对象的基本思想是 numpy 的方式是自定义 __getitem__
方法 - 逗号分隔的值作为元组呈现给方法 - 您只需将元组中的值用作按顺序索引嵌套字典。
除此之外,Python 可以轻松地使用 collections.abc 类创建功能齐全的 dict 等价物:如果您在继承 collections[.abc].MutableMapping
时实现最小的方法集,则所有字典行为都会被模拟 - (__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))
你准备好了:
>>> from nesteddict import NestedDict
>>> x = NestedDict(a=)
NestedDict('a': )
>>> x["a", "b"] = 10
>>> x
NestedDict('a': 'b': 10)
>>> x["a", "c", "e"] = 25
>>> x
NestedDict('a': 'c': 'e': 25, 'b': 10)
>>> x["a", "c", "e"]
25
>>>
请注意,这是一个高级实现,它可以正常工作,但您将无法达到在 NumPy 上获得的优化级别 - 相反。如果您需要在这些对象中执行快速数据操作,您也许可以检查“cython” - 或者诉诸将 dict 键转换为数字键并使用 NumPy 的想法(这个想法仍然可以从这个答案中挑选一些想法)
【讨论】:
BrenBarn 的 pandas 建议可以满足我的大部分需求,尽管它似乎不允许 NestedDict['a', 'x']。正如你所描述的那样,用__getitem__
和__setitem__
在 pandas 上包裹一层薄薄的层会将它们拉到一起。【参考方案3】:
使用熊猫 假设文件是这样的:
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
【讨论】:
以上是关于Python如何用字符串键索引多维数组,如字典的主要内容,如果未能解决你的问题,请参考以下文章