Python如何使用字符串键索引多维数组,就像dict一样

时间:2015-05-12 18:39:42

标签: python numpy dictionary indexing pandas

我想将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索引错误...

3 个答案:

答案 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