Numpy's array class is called ndarray. It is also known by the alias array. Note that numpy.array is not the same as the Standard Python Library class array.array, which only handles one-dimensional arrays and offers less functionality.
In [4]:
from numpy import *
In [5]:
arange(15)
Out[5]:
In [6]:
arange(15).reshape(3,5)
Out[6]:
In [8]:
a = arange(15).reshape(3,5)
a
Out[8]:
In [9]:
a.ndim
Out[9]:
In [10]:
a.dtype
Out[10]:
In [11]:
a.dtype.name
Out[11]:
In [12]:
type(a)
Out[12]:
In [13]:
# A frequent error consists in calling array with multiple numeric arguments, rather than providing
# A single list of numbers as an argument.
# Wrong
a = array(1,2,3,4)
In [14]:
# Right
a = array([1,2,3,4])
In [16]:
# Type of array can be explicitly specified during creation
c = array ([(1,2),(3,4)], dtype=complex)
In [17]:
c
Out[17]:
In [19]:
# Examples of array creation
# By default all arrays are float64
zeros ( (3,4))
Out[19]:
In [20]:
ones( (2,3))
Out[20]:
In [21]:
# 3-D Array
# 2 sets, each array = 3 X 4
ones ( (2,3,4))
Out[21]:
In [23]:
# Empty = initial state is random
empty ( (2,3))
Out[23]:
In [24]:
# Create Sequences of Numbers
# The functions returns arrays instead of lists
arange (10, 35, 5)
Out[24]:
In [25]:
arange (1, 2, .2) # Works also with floats
Out[25]:
In [26]:
# But
# When arrays are created with float, it is generally not possible
# To determine the number of elements due to the finite
# Floating Point Precision
# Hence
# It is better to create them with linspace
In [27]:
linspace (0, 2, 9) # 9 numbers from 0 to 2
Out[27]:
In [29]:
# If array is too large, numpy prints ...
# This can be disabled with set_printoptions(threshold='nan')
arange (0, 100000)
Out[29]:
In [49]:
# Arithmetic Operations are element-wise
a = array([1,2,3,4])
b = arange(4)
In [50]:
a
Out[50]:
In [51]:
b
Out[51]:
In [52]:
a - b
Out[52]:
In [53]:
a ** 2
Out[53]:
In [54]:
a < 3
Out[54]:
In [55]:
# The * operator applies element-wise
a = array ( [[1,2], [2,3]])
b = array ( [[2,3], [4,5]])
In [56]:
a * b
Out[56]:
In [57]:
# Dot Product
dot (a,b)
Out[57]:
In [58]:
# Operators such as += and *= modifies array in place
In [59]:
a
Out[59]:
In [60]:
a += 10
In [61]:
a
Out[61]:
In [62]:
b
Out[62]:
In [63]:
a += b
In [64]:
a
Out[64]:
In [65]:
b
Out[65]:
In [70]:
# When different array types are operated, they are upcasted
a = ones (3, dtype=int32)
b = linspace (0, pi, 3)
b.dtype.name
Out[70]:
In [71]:
c = a + b
In [72]:
c
Out[72]:
In [73]:
c.dtype.name
Out[73]:
In [74]:
# Many unary methoda are implemented in numpy
a = random.random ((2,3))
In [75]:
a
Out[75]:
In [76]:
a.sum()
Out[76]:
In [77]:
a.min()
Out[77]:
In [78]:
a.max()
Out[78]:
In [82]:
# These operates across the entire array, as if it were a
# List of Numbers
# You can specify the axis parameter to change this default behaviour
b = arange(15).reshape(3,5)
In [83]:
b
Out[83]:
In [84]:
b.sum()
Out[84]:
In [85]:
b.sum(axis=0) # Sum of each column
Out[85]:
In [86]:
b.min(axis=1) # Min of each row
Out[86]:
In [87]:
b.cumsum(axis=1) # Cumulative Sum Across Row
Out[87]:
In [88]:
a = arange (10) ** 2
In [89]:
a
Out[89]:
In [90]:
a[2]
Out[90]:
In [91]:
a[2:5]
Out[91]:
In [92]:
a[:6:2] # Equivalent to a[0:6:2]
Out[92]:
In [93]:
# a[:6:2] == a[0:6:2] == From start (0) to 6 in steps of 2
In [94]:
a[0:6:2] = - 10
In [95]:
a
Out[95]:
In [96]:
a[::-1] # Start to End in -1 Steps = Reverse the Array
Out[96]:
In [97]:
a[:]
Out[97]:
In [99]:
a[:1]
Out[99]:
In [100]:
# Multidimensional Arrays
In [101]:
def f(x,y):
return 10 * x + y
b = fromfunction(f,(5,4), dtype=int)
b
Out[101]:
In [102]:
b[2,3]
Out[102]:
In [103]:
b[0:5,1] # Rows 0-5, Column 1
Out[103]:
In [104]:
b[:1] # First 1 ELEMENT of B
Out[104]:
In [107]:
b[:2] # First 2 ELEMENTS of B
Out[107]:
In [112]:
# But
b[:,1] # The 1st Column in All Elements of b
Out[112]:
In [113]:
b[:,2] # The 2nd Column in All Elements of b
Out[113]:
In [116]:
b[:,2:4] # The 2nd - 3rd Column in All Elements of b
Out[116]:
In [117]:
b[:0] # No ELEMENTS of B
Out[117]:
In [118]:
b[1] # First Element
Out[118]:
In [119]:
b[:] # All ELEMENTS of B
Out[119]:
In [120]:
# When indices are missing, the missing indices are considered complete slices
b[-1] # == b[-1,:] == last row in all columns
Out[120]:
In [129]:
c = array( [
[[1,2],[2,3]],
[[10,20],[30,40]]
])
In [130]:
c.shape
Out[130]:
In [131]:
c[1,]
Out[131]:
In [132]:
c[1,...
Out[132]:
In [134]:
c[...,1] # The 1st column in each element in each element of c
Out[134]:
In [135]:
# Iterating over array
b
Out[135]:
In [136]:
for row in b:
print row
In [139]:
for row in b[0:1]:
for element in row:
print element
In [142]:
# Alternatively one can "FLATTEN" the array
for element in b[0:1].flat:
print element
In [162]:
# The shape of an array can be changed with various commands
a = floor (10*random.random((3,4)))
In [163]:
a
Out[163]:
In [164]:
a.shape
Out[164]:
In [165]:
a.flat # This is an object (iterator)
Out[165]:
In [167]:
a.ravel() # This razes to 1st level
Out[167]:
In [168]:
# Now you can change the shape
In [169]:
a.shape = (4,3) # Essentially I am transposing
a
Out[169]:
In [161]:
a.transpose() # This will bring us back the original array
Out[161]:
In [171]:
a
Out[171]:
In [174]:
a.resize((3,4))
In [175]:
a
Out[175]:
In [176]:
# If -1 is given as a reshaping option, the other
# Dimensions are automatically calculated
a.reshape(3,-1)
Out[176]:
In [197]:
# Stacking Arrays
a = floor(10*random.random((2,2)))
b = floor(10*random.random((2,2)))
In [198]:
a
Out[198]:
In [199]:
b
Out[199]:
In [200]:
vstack((a,b))
Out[200]:
In [201]:
hstack((a,b))
Out[201]:
In [202]:
# Column stack stacks 1D arrays as columns into a 2D array
column_stack((a,b))
Out[202]:
In [203]:
row_stack((a,b))
Out[203]:
In [204]:
a = array([1,2])
b = array([10,20])
a
Out[204]:
In [205]:
b
Out[205]:
In [206]:
a[:,newaxis] # This allows 2D column vectors
Out[206]:
In [207]:
b[:,newaxis]
Out[207]:
In [208]:
column_stack((a[:,newaxis], b[:,newaxis]))
Out[208]:
In [209]:
vstack((a[:,newaxis], b[:,newaxis]))
Out[209]:
In [210]:
# Row Stack
row_stack((a[:,newaxis], b[:,newaxis]))
Out[210]:
In [211]:
# One can also use r_ and c_ to create arrays
r_[1:4,0,4]
Out[211]:
In [233]:
# Splitting an array into several smaller ones
random.seed(seed=1)
a = floor (10 * random.random((2,10)))
In [234]:
a
Out[234]:
In [235]:
hsplit(a,5) # Split into 5 arrays
Out[235]:
In [236]:
hsplit(a,(3,4)) # Splits after the 3rd and 4th columns
Out[236]:
In [237]:
# No Copy
a = arange(12)
b = a
b is a
Out[237]:
In [238]:
b.shape = (3,4)
In [240]:
# Shape of a also changes
a.shape
Out[240]:
In [241]:
# Python passes mutable objects as references
# So, function calls make no copy
def f(x):
return id(x)
id(a)
Out[241]:
In [242]:
print f(a)
In [243]:
id(a) == f(a)
Out[243]:
In [244]:
# Shallow Copy
# Different Array Objects can share the same data
# The 'view' method creates a new array obj that looks at the same data
# c is "looking at a"
# If you change c values, a's values will also change
c = a.view()
c is a
Out[244]:
In [245]:
c.base
Out[245]:
In [246]:
c.base is a
Out[246]:
In [247]:
c.flags.owndata
Out[247]:
In [248]:
c.shape = 2,6
In [249]:
a.shape # This does not change
Out[249]:
In [250]:
c.shape # But this is still "looking at a"
Out[250]:
In [256]:
# So, if we change some value in c, it will also change in a
c[1,1] = 1000
In [257]:
a
Out[257]:
In [263]:
# Slicing an Array also returns a view of it
s = a[:,1:3] # All Rows, Columns 1-2
s
Out[263]:
In [264]:
# s is a "view" of a
# So, if we change s
# It will also change a
s[:] = 99
In [265]:
a
Out[265]:
In [266]:
# Deep Copy
# Makes a complete copy of the object
d = a.copy()
In [267]:
d is a
Out[267]:
In [273]:
a = arange(12)**2
a
Out[273]:
In [274]:
i = array( [ 0, 1, 2])
In [275]:
a[i] # Elements of a at positions 0, 1 and 2
Out[275]:
In [277]:
# Bi-dimensional indexing
j = array([[0,1],[1,2]])
a[j]
Out[277]:
In [278]:
palette = array( [
[0,0,0], # black
[255,0,0], # red
[0,255,0], # green
[0,0,255], # blue
[255,255,255] ] )
In [279]:
image = array( [ [ 0, 1, 2, 0 ], [ 0, 3, 4, 0 ] ] )
In [281]:
palette[image] # image = array( [ [ 0, 1, 2, 0 ], [ 0, 3, 4, 0 ] ] )
# 0 0 0 corresponds to palette[0]
# 255 0 0 corresponds to palette[1]
# 0 255 0 corresponds to palette[2]
# 0 0 0 corresponds to palette[0]
# ... and so on
Out[281]:
In [300]:
# We can also give indices for more than one dimension
s = arange(12).reshape(2,2,3)
s
Out[300]:
In [301]:
i = array([0,1]) # Indices for the 1st dimension
In [304]:
j = array([1,0]) # Indices for the 2nd dimension
In [306]:
# i = 0,1 as 1st arg == 1st element of the 0th element of a
# j = 1,0 as 2nd arg == 0th element of the 1st element of a
# Hence, from above
# s[i,j] == 3,4,5 and 6,7,8
s[i,j]
Out[306]:
In [307]:
# You can put i,j in a list and index with the list
l = [i,j]
s[l]
Out[307]:
In [311]:
t = array([i,j])
t
Out[311]:
In [312]:
tuple(t) # Two separate arrays, like i and j in a tuple
Out[312]:
In [310]:
s[tuple(t)]
Out[310]:
In [313]:
# Another common use is the search for max of time series
time = linspace (20, 145, 5)
data = sin (arange(20)). reshape(5,4)
time
Out[313]:
In [314]:
data
Out[314]:
In [316]:
ind = data.argmax(axis=0) # Find the "index" of the maxima of each series
ind
Out[316]:
In [317]:
time_max = time[ind] # Times corresponding to data max
time_max
Out[317]:
In [319]:
data.shape
Out[319]:
In [320]:
data.shape[1]
Out[320]:
In [321]:
xrange(data.shape[1]) # Similar to range, more efficient for large objects
Out[321]:
In [318]:
# data[ind, xrange(data.shape[1])] == data[ind[0],0], data[ind[1],1]...
data_max = data[ind, xrange(data.shape[1])]
data_max
Out[318]:
In [323]:
# Much easier
data.max(axis=0)
Out[323]:
In [336]:
a = arange(5) + 1
a
Out[336]:
In [337]:
a[[1,3,4]]
Out[337]:
In [338]:
a[[1,3,4]] = [100,200,300]
a
Out[338]:
In [339]:
a[[0,0,2]]
Out[339]:
In [340]:
# However, you have to be careful when you use this method
# With +=,... it will only modify the elements representing the indices
# Hence, a[[0,0,2]] += 1 adds 1 to a[0] and a[2] and prints indices 0,0,2
a[[0,0,2]] + 1
Out[340]:
In [341]:
# But
a[[0,0,2]] += 1
a
Out[341]:
In [348]:
a = arange(12).reshape(3,4)
a
Out[348]:
In [349]:
b = a > 4
b
Out[349]:
In [350]:
a[b]
Out[350]:
In [351]:
a[b] = 0 # All elements > 4 set to 0
a
Out[351]:
In [352]:
a = arange(12).reshape(3,4)
a
Out[352]:
In [354]:
b = array([False,True,True])
a[b,:] # Show only rows 1-2, and all columns
Out[354]:
In [355]:
a[b,b] # The intersection of Rows 1-2, Columns 1-2 (See a above)
Out[355]:
In [373]:
# The ix_() Function
# The ix_ function can be used to combine different vectors
# so as to obtain the result for each n-uplet. For example,
# if you want to compute all the a+b+c for all the triplets
# taken from each of the vectors a, b and c:
a = array([0,1,2,3])
b = array([10,20,30])
c = array([100,200,300,400,500])
ax,bx,cx = ix_(a,b,c)
In [374]:
ax
Out[374]:
In [375]:
bx
Out[375]:
In [376]:
cx
Out[376]:
In [377]:
ax.shape, bx.shape, cx.shape
Out[377]:
In [378]:
result = ax+bx+cx
result
Out[378]:
In [379]:
result[3,2,4]
Out[379]:
In [381]:
a[3] + b[2] + c[4] # !!
Out[381]:
In [382]:
# Simple array operations include
# a.transpose()
# a.inv()
# eye(2) # Unit 2 X 2 Matrix
# dot (a,b) # Dot product
# solve (see below)
# eig(a)
# trace(a) # Sum across diagonals
In [396]:
x = array([[1,2],[3,7]])
y = array([10,20])
In [397]:
linalg.solve(x,y)
Out[397]:
In [399]:
trace(x)
Out[399]:
In [414]:
A = arange(12)
A
Out[414]:
In [416]:
A.shape = (3,4)
M = mat(A.copy())
print type(A),"\n", type(M)
In [417]:
A
Out[417]:
In [421]:
M
Out[421]:
In [422]:
M.T
Out[422]:
In [423]:
M.I
Out[423]:
In [426]:
# Automatic Reshaping
# Use -1 to indicate "whatever is needed"
a = arange(30)
a.shape = (2,-1,3)
a
Out[426]:
In [427]:
a.shape
Out[427]:
In [ ]: