2016-06-29 84 views
3

我想創建一個我的排序numpy數組的差異,如果我記錄第一行的值和差異,我可以重新創建原始表,但存儲較少的數據。Numpy和差異()

因此,這裏的表的例子:

my_array = numpy.array([(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 
         (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), 
         (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), 
         (9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 34), 
         (9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 35), 
         (9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36) 
         ],'uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8') 

運行numpy.diff(my_array)後,我預料這樣的事情:

[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), 
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), 
(9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 32), 
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), 
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1) 
] 

注意:以上數據來自 「真實」數據的最後三行,其數量要大得多。對於完整的數據集,差異後的大部分 行將爲0,0,0,0,0,0,0,0,0,0,0,0,1 - 可將a) 存儲在一個小得多的結構,和b)將在磁盤上非常好地壓縮,因爲大多數行包含非常相似的數據。

我應該指出,我有一大堆uint8的原因是因爲我需要在儘可能少的內存中存儲一​​個非常大的數組。最大的數字是185439173519100986733232011757860,這對uint64來說太大了。實際上,要存儲它的最小位數將是108位,或14個字節(到最近的字節)。因此,爲了適應這些大量引入numpy的,我用下面的兩個功能:

def large_number_to_numpy(number,columns): return tuple((number >> (8*x)) & 255 for x in range(columns-1,-1,-1))

def numpy_to_large_number(numbers): return sum([y << (8*x) for x,y in enumerate(numbers[::-1])])

這是用這樣的:

>>> large_number_to_numpy(185439173519100986733232011757860L,14) (9L, 36L, 146L, 73L, 36L, 146L, 73L, 36L, 146L, 73L, 36L, 146L, 73L, 36L)

numpy_to_large_number((9L, 36L, 146L, 73L, 36L, 146L, 73L, 36L, 146L, 73L, 36L, 146L, 73L, 36L)) 185439173519100986733232011757860L

用這樣的數組創建:

my_array = numpy.zeros(TOTAL_ROWS,','.join(14*['uint8']))

然後填充:

my_array[x] = large_number_to_numpy(large_number,14)

而是我得到這個:

>>> my_array 
array([(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 
     (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), 
     (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), 
     (9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 34), 
     (9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 35), 
     (9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36)], 
     dtype=[('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1'), ('f3', 'u1'), ('f4', 'u1'), ('f5', 'u1'), ('f6', 'u1'), ('f7', 'u1'), ('f8', 'u1'), ('f9', 'u1'), ('f10', 'u1'), ('f11', 'u1'), ('f12', 'u1'), ('f13', 'u1')]) 
>>> numpy.diff(my_array) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 1567, in diff 
    return a[slice1]-a[slice2] 
TypeError: ufunc 'subtract' did not contain a loop with signature matching types dtype([('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1'), ('f3', 'u1'), ('f4', 'u1'), ('f5', 'u1'), ('f6', 'u1'), ('f7', 'u1'), ('f8', 'u1'), ('f9', 'u1'), ('f10', 'u1'), ('f11', 'u1'), ('f12', 'u1'), ('f13', 'u1')]) dtype([('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1'), ('f3', 'u1'), ('f4', 'u1'), ('f5', 'u1'), ('f6', 'u1'), ('f7', 'u1'), ('f8', 'u1'), ('f9', 'u1'), ('f10', 'u1'), ('f11', 'u1'), ('f12', 'u1'), ('f13', 'u1')]) dtype([('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1'), ('f3', 'u1'), ('f4', 'u1'), ('f5', 'u1'), ('f6', 'u1'), ('f7', 'u1'), ('f8', 'u1'), ('f9', 'u1'), ('f10', 'u1'), ('f11', 'u1'), ('f12', 'u1'), ('f13', 'u1')]) 
+1

我想問題 是你有複合數據(元組值),沒有定義減法。你爲什麼不使用一個簡單的'uint8'值2d數組?你只需要將定義中的所有'uint8'字符串改爲單個''uint8''。 –

+1

數組行的數據類型不同。我猜python不知道如何減去這樣的數據類型。也許'my_array = int(my_array)'會工作。 – Aguy

回答

4

的問題是,你有一個結構化的陣列,而不是普通的2維數組,所以numpy不知道如何減去一個元組與另一個元組。

將您的結構化陣列規則陣列(from this SO question):

my_array = my_array.view(numpy.uint8).reshape((my_array.shape[0], -1)) 

,然後做numpy.diff(my_array, axis=0)

或者,如果可以的話,避免通過定義my_array作爲

numpy.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], 
      [9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 34], 
      [9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 35], 
      [9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36]], 
      dtype=numpy.uint8) 
+1

請注意,只傳遞'dtype ='uint8'而不是'dtype ='uint8,uint8,...''應該會得到相同的結果。即使使用元組輸入。 –

+0

謝謝Alberto和Andras的幫助 - 我現在看到這是因爲我有一個奇怪的數據類型正在進行。不幸的是,我不知道該怎麼做才能解決這個問題,因爲我的數組從空開始並被填充(就像結構化數組一樣)。我在原帖中增加了更多細節。希望有所幫助。同時,如果我將dtype設置爲單個uint8,則我會看到是否所有東西都「正常工作」。祝一切順利! –

+1

如果您在'large_number_to_numpy'函數中將'tuple'更改爲'numpy.array',那麼該怎麼辦? –

0

感謝阿爾貝託和安德拉什創建結構數組,這裏是我需要做的:從

更改我的數組:

my_array = numpy.zeros(6,'uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8') 

要:

my_array = numpy.zeros((6,14),'uint8') 

我完全不知道爲什麼一個與另一個不同,但我想這只是如何滾滾而來。

然後我就可以填充:

my_array[0] = large_number_to_numpy(0,14) 
my_array[1] = large_number_to_numpy(1,14) 
my_array[2] = large_number_to_numpy(2,14) 
my_array[3] = large_number_to_numpy(185439173519100986733232011757858,14) 
my_array[4] = large_number_to_numpy(185439173519100986733232011757859,14) 
my_array[5] = large_number_to_numpy(185439173519100986733232011757860,14) 

生成:

array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], 
     [ 9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 34], 
     [ 9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 35], 
     [ 9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36]], dtype=uint8) 

而且隨着numpy.diff(my_array,1,0)版本比較給:

array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [ 9, 36, 146, 73, 36, 146, 73, 36, 146, 73, 36, 146, 73, 32], 
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], dtype=uint8) 

這是完美的:)

+2

您最初創建了一個結構化數組,其中包含一個複合'dtype'(14個命名字段),另一個數組是一個2d數組,其中包含一個簡單的'dtype '','uint8'。命名字段和索引字段之間的區別很重要 – hpaulj

+0

從您的意見中可以看出,在使用方式上存在着根本性差異,命名字段用於不同的命名系列數據,如年度GDP國家數量,而二維數組在數學上更純粹,像屏幕上的像素矩陣,或任何其他n維數據最終數據集。 –