2015-11-05 66 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