2013-11-05 96 views
0

我試圖通過陣列的兩個維度組織大塊numpy ndarray(最多16個維度的〜1mil條目的集合)組成兩個子組。在不更改密鑰類型的情況下使用itertools.groupby?

目前,我使用itertool的groupby功能,但它會在我的字典裏的值是itertools._grouper對象,在我的ndarray似乎被轉換爲grouper對象,無論我做什麼。

雖然我可以自定義groupby函數來解決這個問題,但是在我的Python編程能力中,這似乎是一個基本問題,Python是一種非常新的語言,不確定如何防止這種情況發生,或者轉換grouper對象回到帶有正確字段的ndarray中。我需要ndarray,因爲它的字段需要保留以供日後操作。

如何修復以下代碼,將返回的groupby結果完全轉換回ndarray或阻止轉換?

array = np.sort(array, order=['Front','Back','SecStruc']) 
front_dict = dict((k,v) for k,v in groupby(array, lambda array : array['Front'])) 
for key in front_dict: 
    front_dict[key] = dict((k,list(v)) for k,v in groupby(front_dict[key], 
    lambda array : front_dict[key]['Back'])) 

謝謝!

+0

你壓痕似乎有點可疑。 ..care要解決這個問題? – kindall

+0

做什麼最好的方法是?我試圖強制執行每行79個字符的限制,但效果並不理想。 – calben

+0

現在看起來更好! – kindall

回答

2

我想你可能可以使用numpy.split這個。你可以做這樣的事情分成數組爲子陣列:

import numpy as np 

def findsplit(a): 
    diff = a[1:] != a[:-1] 
    edges = np.where(diff)[0] 
    return edges + 1 

array = np.array([0,0,0,1,1,1,1,2,2,3,4,4,4]) 
s = np.split(array, findsplit(array)) 
for a in s: 
    print a 
# [0 0 0] 
# [1 1 1 1] 
# [2 2] 
# [3] 
# [4 4 4] 

爲了讓你在你的問題,你可以不喜歡discribe嵌套的字典:

byFront = np.split(array, findsplit(array['Front'])) 
front_dict = {} 
for sameFront in byFront: 
    back_dict = {} 
    byBack = np.split(sameFront, findsplit(sameFront['Back'])) 
    for sameBack in byBack: 
     back_dict[sameBack['Back'][0]] = sameBack 
    front_dict[sameFront['Front'][0]] = back_dict 
0

看起來你幾乎就在那裏。 list(v)是一個列表,可以輕鬆轉換爲數組。

x=np.array([0,0,0,1,1,1,1,2,2,3,4,4,4]) 
{k:np.array(list(v)) for k,v in groupby(x)} 

{0: array([0, 0, 0]), 
1: array([1, 1, 1, 1]), 
2: array([2, 2]), 
3: array([3]), 
4: array([4, 4, 4])} 

或與2d數組(在第1列,然後在最後一列)。

x=np.array([[0,1,2],[1,2,3],[1,2,4],[1,0,4],[2,3,1]]) 
d={k:list(v) for k,v in groupby(x,lambda s:s[0])} 
print d 
# {0: [array([0, 1, 2])], 
# 1: [array([1, 2, 3]), array([1, 2, 4]), array([1, 0, 4])], 
# 2: [array([2, 3, 1])]} 
for i in d.keys(): 
    d[i]={k:np.array(list(v)) for k,v in groupby(list(d[i]),lambda s:s[2])} 
print d 
# {0: {2: array([[0, 1, 2]])}, 
# 1: {3: array([[1, 2, 3]]), 4: array([[1, 2, 4], [1, 0, 4])}, 
# 2: {1: array([[2, 3, 1]])}} 
print d[1][4] 
# [[1 2 4] 
# [1 0 4]] 

它沒有多大關係我是否使用list(v)np.array(list(v)) - 在任一階段(前提是你有興趣的迭代一號尺寸)。使用


改編自numpy的文檔

x = np.array([(1.5,2.5,(1.0,2.0)),(1.5,2.5,(2.0,4.0)),(3.,4.,(4.,5.)),(1.,3.,(2.,6.))], 
     dtype=[('x','f4'),('y',np.float32),('value','f4',(2,2))]) 
d={k:list(v) for k,v in groupby(x,lambda s:s['x'])} 
for i in d.keys(): 
    d[i]={k:list(v) for k,v in groupby(list(d[i]),lambda s:s['y'])} 
pprint(d) 
for dd in d[1.5][2.5]: 
    print dd 
print d[1.5][2.5][0].dtype 
# [('x', '<f4'), ('y', '<f4'), ('value', '<f4', (2, 2))] 
dd = np.array(d[1.5][2.5],dtype=x.dtype) 
print dd 
print dd.dtype 
print dd[0] 
# (1.5, 2.5, [[1.0, 2.0], [1.0, 2.0]]) 
print dd['value'] 
# [[[ 1. 2.] [ 1. 2.]] 
# [[ 2. 4.] [ 2. 4.]]] 

的「最內」分子的結構化陣列字符被保留結構化陣列。如果我想將這些數組的列表變成一個數組(例如dd),我只需要使用np.array(...,dtype=x.dtype)

d[1.5][2.5][0]['value']1.52.5是字典鍵,0是列表索引,和value是一個結構陣列的字段名稱。


但是這個groupby真的需要用嗎?我可以用普通的numpy索引獲得最後的'價值'。並且x的'行'不必被排序。對於非常大的陣列,速度和內存使用可能是重要的考慮因素。

I=(x['x']==1.5)&(x['y']==2.5) 
print x[I]['value'] 
+0

當直接轉換爲Numpy數組時,我使用緩衝區獲得了一個帶有對象成員的無效數組。我不確定那是什麼。 之後轉換爲Numpy數組時,Numpy數組不維護字段標籤。 – calben

+0

我的測試用例使用純數字數組。將它轉換爲列表並很容易。 'groupby'是一個Python函數,可用於列表和生成器。您正在使用結構化數組。看看'array.tolist()'產生了什麼。這就是'groupby'將要處理的事情。將'groupby'生成的列表轉換回數組時,您需要指定'dtype',例如'np.array(列表(v)中,D型細胞= array.dtype)'。 – hpaulj

+0

試過了。它給出了一個void類型的錯誤。除非有一個非常明確的數據集,否則創建np數組容易出現void類型錯誤。否則,您的解決方案更加優雅。 – calben

相關問題