python - 来自任意级别嵌套字典的 numpy 结构化数组

标签 python arrays numpy dictionary nested

我有一个任意级别的嵌套字典,其中包含字段名称作为键,以及与值大小相同的一维 numpy 数组,例如:

d = {'a' : arr1, 'b' : {'b1' : arr2, 'b2' : {'c' : arr3}}}

是否有一种简单的方法可以从中构建反射(reflect)原始层次结构的 numpy 结构化数组?另外,如果给出了 OrderedDict ,则最好保留字段名称顺序。常用的np.arraynp.asarraynp.rec.array函数似乎没有帮助。

最佳答案

大多数情况下,这可以通过两个步骤完成。构造与字典布局相对应的复合数据类型。然后用字典中的数组填充一个空数组。

构建示例字典:

In [94]: arr1=np.arange(10)
In [95]: arr2=np.arange(100.,110.)
In [96]: arr3=np.arange(200,210)
In [98]: d={'a':arr1, 'b':{'b1':arr2, 'b2':{'c':arr3}}}

该函数构造数据类型:

def mkdt(d):
    ll = []
    for k,v in d.items():
        if isinstance(v,np.ndarray):
            ll.append((k,v.dtype))
        else:
            ll.append((k,mkdt(v)))
    return ll

In [176]: np.dtype(foo(d))
Out[176]: dtype([('a', '<i4'), ('b', [('b1', '<f8'), ('b2', [('c', '<i4')])])])

此函数将数据值从 d 复制到 A:

def copy_values(d, A):
    if A.dtype.names:
        for n in A.dtype.names:
            copy_values(d[n], A[n])
    else:
        A[:]=d

In [264]: A=np.zeros(d['a'].shape,dt)    
In [265]: copy_values(d,A)
In [266]: A
Out[266]: 
array([(0, (100.0, (200,))), (1, (101.0, (201,))), (2, (102.0, (202,))),
       (3, (103.0, (203,))), (4, (104.0, (204,))), (5, (105.0, (205,))),
       (6, (106.0, (206,))), (7, (107.0, (207,))), (8, (108.0, (208,))),
       (9, (109.0, (209,)))], 
      dtype=[('a', '<i4'), ('b', [('b1', '<f8'), ('b2', [('c', '<i4')])])])

(早期解决方案)

这是一个交互式 (ipython) session ,它将数据从像您这样的字典传输到结构化数组。

In [94]: arr1=np.arange(10)
In [95]: arr2=np.arange(100,110)
In [96]: arr3=np.arange(200,210)
In [98]: d={'a':arr1, 'b':{'b1':arr2, 'b2':{'c':arr3}}}

匹配的数据类型:.

In [100]: dt=np.dtype([('a','i'), ('b', np.dtype([('b1','i'),('b2',np.dtype([('c','i')]))]))])

创建一个正确大小和类型的空数组,并填充字段

In [102]: A=np.zeros((10,),dt)    
In [104]: A['a']=d['a']
In [105]: A['b']['b1']=d['b']['b1']
In [106]: A['b']['b2']['c']=d['b']['b2']['c']

In [107]: A
Out[107]: 
array([(0, (100, (200,))), (1, (101, (201,))), (2, (102, (202,))),
       (3, (103, (203,))), (4, (104, (204,))), (5, (105, (205,))),
       (6, (106, (206,))), (7, (107, (207,))), (8, (108, (208,))),
       (9, (109, (209,)))], 
      dtype=[('a', '<i4'), ('b', [('b1', '<i4'), ('b2', [('c', '<i4')])])])

如果所有字段都是相同的数据类型(此处为 int),则该数组也可以构造为二维数组上的 View :

np.column_stack([arr1,arr2,arr3]).view(dt).ravel()

这是有效的,因为 (10,3) 数组具有与结构化数组相同的数据缓冲区布局。


from numpy.lib import recfunctions

允许访问一些实用功能。

recfunctions.recursive_fill_fields 例如,可以将数据从 A 复制到相同数据类型的另一个数组(但不能从 column_stack 复制。它使用递归处理嵌套数据类型。

In [149]: recfunctions.flatten_descr(dt)
Out[149]: (('a', dtype('int32')), ('b1', dtype('int32')), ('c', dtype('int32')))

使您的嵌套变平。

In [150]: recfunctions.get_fieldstructure(dt)
Out[150]: {'a': [], 'b': [], 'b1': ['b'], 'b2': ['b'], 'c': ['b', 'b2']}

这些函数如何处理复杂的数据类型可能比它们实际所做的更有用。看一下代码。

关于python - 来自任意级别嵌套字典的 numpy 结构化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32328889/

相关文章:

python - 鸡蛋和零件之间的构建有什么区别?

javascript - 拆分字符串但保留逗号

python - 对值进行分组并检查另一列中的值是否在 python pandas dataframe 中相互抵消

python - 用条件替换数组中的值

python - 文件 "<string>"第 1 行,在 <module> 中 NameError : name ' ' is not defined in ATOM

python - 在导入模块后的 python 中,有没有办法找到它是从哪个物理文件加载的?

python - sklearn GaussianNB - 结果不好,[nan] 概率

java - 仅生成正随机数并对它们进行排序

python - 如果循环输出错误

Python从矩阵的每一行中减去第一个元素