2015-11-05 38 views
2

是否有一种调整numpy结构化dtype的好方法,而不必每次都重新构建整个dtype?我目前有一个机制来做到这一点,但我很好奇,如果有更有效的方法。为了说明我在问什么,我提供了一些代码。基本思想是我想调整特定名称的数据类型。调整结构化数据的Numpy Dtype的最佳方法

def resize_dtype(orig_type, resized_type): 
    # I have a bunch of logic in here to loop and build new_array 
    return new_dtype 

def test_resize_dtype(): 
    type1 = np.dtype({'names':['col1', 'col2'], 'formats':['2i' ,'4i']}) 
    type2 = np.dtype({'names':['col', 'descr'], 'formats':[5*type1, 'S32']}) 

    tmp = np.dtype({'names':['col1', 'col2'], 'formats':['10i' ,'4i']}) 
    desired_type = np.dtype({'names':['col', 'descr'], 'formats':[5*tmp, 'S32']}) 
    resized_type = np.dtype([('col1', '10i')]) 
    new_type = resize_dtype(type2, resized_type) 
    assert new_type == desired_type 

回答

1

这不公平。您展示测试框架,但没有实际确定大小的代码。乍看之下,test_resize_dtype看起来像是专注于修改np.dtype对象。但是在定义了一堆dtypes之后,它所做的只是调用一个未知的resize_array - 或者是一个错字,而且您确实打算调用近似未知的resize_dtype函数?

但我想指出,您的主要目标是将嵌套dtype的内部数组大小从改为(10,)

据我所知,没有一种整洁或有效的方式来改变这样一个数组。你只需要用新的dtype创建一个新阵列,然后将数据逐场复制,从旧到新,并根据需要调整形状。

X.dtype定义numpy如何查看数组X的每个元素。 reshapetranspose会影响它如何处理X的元素,但在这些元素的内部不做任何事情。您对dtype的更改不仅会改变元素中字节的解释,还会改变其大小。所以没有办法重用原始的X数据缓冲区。

numpy.lib.recfunctions有一堆用于rec数组和结构化数组的工作,包括添加字段等。我已经检查过的结果是将字段从旧到新逐个拷贝 - 如果需要,递归地嵌套dtypes。但是,您的调整可能超出其能力。

In [92]: X1=np.zeros(1,dtype=type2) 

In [93]: X2=np.zeros(1,dtype=desired_type) 

In [94]: X1.itemsize 
Out[94]: 152 

In [95]: X2.itemsize 
Out[95]: 312 

至于更改现有dtype,您可以编辑其descr,并创建一个新dtype。主要的难题是descr是列表和元组的混合。列表是可变的,元组不是。但这里有一个样本会话:

字段名,至少在顶层,可以直接改变:

In [141]: type2.names=['column','description'] 
In [142]: type2 
Out[142]: dtype([('column', [('col1', '<i4', (2,)), ('col2', '<i4', (4,))], (5,)), ('description', 'S32')]) 

抓住descr,该dtype的列表表示:

In [164]: d2=type2.descr  
In [165]: d2 
Out[165]: 
[('column', [('col1', '<i4', (2,)), ('col2', '<i4', (4,))], (5,)), 
('description', '|S32')] 

... 

d2有足够的信息来重新创建dtype:np.dtype(d2)

d2是元组列表;修改任何这些,我需要将其转换为一个列表:

In [168]: dd2=list(d2[0]) 
In [169]: dd2 
Out[169]: ['column', [('col1', '<i4', (2,)), ('col2', '<i4', (4,))], (5,)] 

dd2嵌入式的是,我们要改变另一个多元组:

In [174]: ddd2=list(dd2[1][0]) 
In [175]: ddd2 
Out[175]: ['col1', '<i4', (2,)] 

In [176]: ddd2[2]=(10,) # change the list  
In [177]: ddd2 
Out[177]: ['col1', '<i4', (10,)] 

写入这个名单(转换回元组)到dd2

In [181]: dd2[1][0]=tuple(ddd2)  
In [182]: dd2 
Out[182]: ['column', [('col1', '<i4', (10,)), ('col2', '<i4', (4,))], (5,)] 

你瞧,我最终改变d2为好。这是因为我在[181]中更改的是嵌套在元组中的列表。我可能不需要首先制作dd2列表。我只是用它来引用内部可变列表。

我现在可以使用d2来制作一个匹配desired_dtype的dtype。

In [183]: d2 
Out[183]: 
[('column', [('col1', '<i4', (10,)), ('col2', '<i4', (4,))], (5,)), 
('description', '|S32')] 

In [184]: np.dtype(d2) 
Out[184]: dtype([('column', [('col1', '<i4', (10,)), ('col2', '<i4', (4,))], (5,)), ('description', 'S32')]) 

In [185]: desired_type 
Out[185]: dtype([('col', [('col1', '<i4', (10,)), ('col2', '<i4', (4,))], (5,)), ('descr', 'S32')]) 

对不起,如果这有点冗长,但我认为探索过程比最终结果更重要。

+0

我留下了调整大小的逻辑,因为它与我的问题没有密切关系。你给的答案并不是我正在寻找的东西。我正在处理的许多数据类型非常庞大和复杂,并且像我为'desired_type'所做的那样手动定义它们并不是真的可行。我希望能够保留相同的确切结构减去我实际想要改变的字段。 – user985030

+0

所以你的重点是操纵核果对象?对'np.dtype'的输入是正常的Python - 列表,元组,字典。你可以编程建立这些。列表和字典部分是可变的。我知道你可以改变现有的dtype对象的字段名称。我不知道其他部分。我不得不在Ipython会话中使用dtype。 – hpaulj

+0

我已经添加了一个关于如何修改'type2'来演示与你的'desire_type'匹配的新dtype的演示。 – hpaulj