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如何用字符串键索引多维数组,如字典的主要内容,如果未能解决你的问题,请参考以下文章

如何用 C 编写散列函数?

如何用postman将一维int数组

c ++:解析包含表达式“访问多维数组”的字符串

python如何减小维度

多维数组索引 C++ 中的多维数组

在 C++ 中返回多维数组的函数