The (nd)array object:
Multidimensional, any type of data
It can be interfaced with other languages...
Nota: the array module exists in python but it is limited to 1d, not to be confused with NumPy's nd-array
In [1]:
import numpy
In [2]:
numpy.array([1, 2, 3, 5, 7, 11, 13, 17])
Out[2]:
From a list of lists for 2D arrays:
In [3]:
numpy.array([[1, 2, 3], [4, 5, 6]])
Out[3]:
Also specifying the type of element:
In [4]:
numpy.array([[1, 2, 3], [4, 5, 6]], dtype=numpy.float64)
Out[4]:
In [5]:
shape = (2,3)
numpy.zeros(shape,dtype="int32")
Out[5]:
In [6]:
numpy.ones(shape,dtype="int32")
Out[6]:
In [7]:
#this is a ipython trick to request help ...
numpy.arange?
In [8]:
numpy.arange(0, 10, 2)
Out[8]:
In [9]:
numpy.identity(3,dtype=numpy.int)
Out[9]:
Arrays can also be generated from index positions using numpy.fromfunction
. This can be combined with lambda-function
In [10]:
lambda_function = lambda i,j: numpy.sin(i) * numpy.cos(j)
numpy.fromfunction(lambda_function, (3,3))
Out[10]:
Numpy array can directly be dumped to and restrored from disk:
In [11]:
a = numpy.ones((3, 5), dtype="complex")
numpy.save('data.npy', a)
b = numpy.load('data.npy')
print(b)
In [12]:
a = [1, 2, 3]
import numpy
b = numpy.array(a)
print(2*a[2])
print(2*a)
print(2*b[2])
print(2*b)
Nota:
It is adviced to explicitly specify the data-type: numpy.uint16
In [13]:
import numpy
a = {'dict':'a'}
b = ['list','b']
c = ('tuple','c')
v = numpy.array([a, b, c,"bla"])
print(v)
In [14]:
img = numpy.zeros((2,2), {'names': ('r','g','b'), 'formats': (numpy.uint8, numpy.uint8, numpy.uint8)})
img["r"] = 10
print(img)
Nd-array are composed of a buffer containing the data (or the pointer to the data) and associated metadata. Multiple array can point on the same buffer, they are called "views" on the array. Modifying one view impacts all others.
Each array has multiple attributes:
In [15]:
a = numpy.arange(6)
a.shape = (2,3)
print(a)
print("dtype: "+str(a.dtype))
print("shape: "+str(a.shape))
print("strides: "+str(a.strides))
print("buffer address: %s"%a.ctypes.data)
In [16]:
b = a.T
print(b)
print("dtype: "+str(b.dtype))
print("shape: "+str(b.shape))
print("strides: "+str(b.strides))
print("buffer address: %s"%b.ctypes.data)
In [17]:
b[0,0] = 10
print(a)
Shape/Strides and views/buffer are quite complex mecanisms ...
One can select elements as with any other Python sequence.
The output refers to the original array and usually it is not contiguous in memory.
In [18]:
a = numpy.arange(24).reshape((6, 4))
print(a)
a[3, 2] #extraction of a single element
Out[18]:
In [19]:
a[3:4, 2] #extraction of the third line, second element
Out[19]:
In [20]:
a[3,:] #same as previous assuming a has at least two dimensions
Out[20]:
In [21]:
a[0, -1] #last element of the first row
Out[21]:
In [22]:
a[0:2, 0:4:2] #slicing allowed
Out[22]:
In [23]:
a[0:2, :] = 5 #assignation is also possible
In [24]:
a>10
Out[24]:
In [25]:
a[a>10]
Out[25]:
In [26]:
a
Out[26]:
In [27]:
X = numpy.array(range(100))
# Nop there is no answer yet :þ
There are really a lot of methods to numpy arrays but the most important ones are (assuming a is an array):
Note that most methods take axis, dtype and out optionnal arguments:
a.sum(axis=None, dtype=None, out=None) Perform the sum along a specified axis
In [28]:
dir(a) #to convince youself
Out[28]:
Definition from wikipedia:
In the context of image processing, binning is the procedure of combining a cluster of pixels into a single pixel. As such, in 2x2 binning, an array of 4 pixels becomes a single larger pixel, reducing the overall number of pixels. This aggregation, reducing the number of data (with a loss of information), facilitates the analysis. For instance, binning the data may also reduce the impact of read noise on the processed image (at the cost of a lower resolution).
In [29]:
img = numpy.arange(6*6)
img.shape = 6,-1
img
Out[29]:
In [30]:
img[::2,::2]+img[1::2,::2]+img[::2,1::2]+img[1::2,1::2]
Out[30]:
In [31]:
c = img.copy()
c.shape = 3,2,3,2
c.sum(axis=-1).sum(axis=1)
Out[31]:
In [31]:
In [34]:
from math import cos, sin
def no_numpy(n,m):
x = []
sinj = [sin(j) for j in range(m)]
for i in range(n):
cosi = cos(i)
l=[0]*m
for j,sj in enumerate(sinj):
l[j] = sj*cosi
x.append(l)
return numpy.array(x)
%timeit no_numpy(1000,1000)
In [35]:
def matlab_like(n,m):
y,x = numpy.ogrid[:n,:m]
return numpy.cos(y)*numpy.sin(x)
%timeit matlab_like(1000,1000)
In [36]:
def optimized(n,m):
msin = numpy.sin(numpy.arange(m))
ncos = numpy.cos(numpy.arange(n))
return numpy.outer(ncos,msin)
%timeit optimized(1000,1000)
Next: Numpy's C optimized libraries
In [ ]: