2015-02-07 15 views
5

Albo ndarray.reshape lub numpy.newaxis może być użyty do dodania nowego wymiaru do tablicy. Obaj wydają się tworzyć pogląd, czy jest jakiś powód lub korzyść, aby użyć jednego zamiast drugiego?Numpy: użyj zmiany kształtu lub newaxis, aby dodać wymiary

>>> b 
array([ 1., 1., 1., 1.]) 
>>> c = b.reshape((1,4)) 
>>> c *= 2 
>>> c 
array([[ 2., 2., 2., 2.]]) 
>>> c.shape 
(1, 4) 
>>> b 
array([ 2., 2., 2., 2.]) 
>>> d = b[np.newaxis,...] 
>>> d 
array([[ 2., 2., 2., 2.]]) 
>>> d.shape 
(1, 4) 
>>> d *= 2 
>>> b 
array([ 4., 4., 4., 4.]) 
>>> c 
array([[ 4., 4., 4., 4.]]) 
>>> d 
array([[ 4., 4., 4., 4.]]) 
>>> 

`

+1

'b.reshape (1, -1)' jest przydatnym skrótem. – hpaulj

Odpowiedz

9

Nie widzę dowodów dużej różnicy. Możesz wykonać test czasu na bardzo dużych tablicach. Zasadniczo zarówno skrzypce z kształtem i ewentualnie kroki. __array_interface__ to dobry sposób na uzyskanie dostępu do tych informacji. Np

In [94]: b.__array_interface__ 
Out[94]: 
{'data': (162400368, False), 
'descr': [('', '<f8')], 
'shape': (5,), 
'strides': None, 
'typestr': '<f8', 
'version': 3} 

In [95]: b[None,:].__array_interface__ 
Out[95]: 
{'data': (162400368, False), 
'descr': [('', '<f8')], 
'shape': (1, 5), 
'strides': (0, 8), 
'typestr': '<f8', 
'version': 3} 

In [96]: b.reshape(1,5).__array_interface__ 
Out[96]: 
{'data': (162400368, False), 
'descr': [('', '<f8')], 
'shape': (1, 5), 
'strides': None, 
'typestr': '<f8', 
'version': 3} 

utworzą widoku, przy użyciu tego samego buforu data jak oryginał. Ten sam kształt, ale zmiana kształtu nie zmienia wartości strides. reshape pozwala określić order.

I .flags pokazuje różnice w flagi C_CONTIGUOUS.

reshape może być szybszy, ponieważ wprowadza mniej zmian. Ale tak czy inaczej operacja nie powinna znacznie wpłynąć na czas większych obliczeń.

np. dla dużych b

In [123]: timeit np.outer(b.reshape(1,-1),b) 
1 loops, best of 3: 288 ms per loop 
In [124]: timeit np.outer(b[None,:],b) 
1 loops, best of 3: 287 ms per loop 

interesująca obserwacja, że: b.reshape(1,4).strides -> (32, 8)

Oto moje przypuszczenie. .__array_interface__ wyświetla atrybut bazowy, a .strides jest bardziej podobny do właściwości (chociaż może być pochowany w kodzie C). Domyślną wartością podstawową jest None, a gdy jest to potrzebne do obliczeń (lub wyświetlania z .strides), oblicza się ją z kształtu i wielkości elementu. 32 to odległość do końca pierwszego rzędu (4x8). np.ones((2,4)).strides ma taką samą (32,8) (i None w __array_interface__.

b[None,:] z drugiej strony przygotowuje tablicę dla nadawania. Kiedy nadawany, istniejące wartości są wielokrotnie wykorzystywane. To właśnie 0 w (0,8) robi.

In [147]: b1=np.broadcast_arrays(b,np.zeros((2,1)))[0] 

In [148]: b1.shape 
Out[148]: (2, 5000) 

In [149]: b1.strides 
Out[149]: (0, 8) 

In [150]: b1.__array_interface__ 
Out[150]: 
{'data': (3023336880L, False), 
'descr': [('', '<f8')], 
'shape': (2, 5), 
'strides': (0, 8), 
'typestr': '<f8', 
'version': 3} 

b1 wyświetla same jak np.ones((2,5)) ale ma tylko 5 przedmiotów.

np.broadcast_arrays jest funkcją w /numpy/lib/stride_tricks.py. wykorzystuje as_strided z tego samego pliku. Te funkcje bezpośrednio grają z atrybutami kształtu i kroku.

+0

Cool, ... '' __array_interface__'''. !! – wwii

+0

Hmmm '' 'b.reshape (1,4) .strides -> (32, 8)' '', '' 'b [Brak, ...]. Kroki -> (0, 8)' '' – wwii

+0

Ciekawy. Dodałem trochę przemyśleń. – hpaulj

Powiązane problemy