In [1]:
mylist = list(range(10))
print(mylist)
Use slicing to produce the following outputs:
[2, 3, 4, 5]
In [2]:
mylist[2:6]
Out[2]:
[0, 1, 2, 3, 4]
In [3]:
mylist[:5]
Out[3]:
[6, 7, 8, 9]
In [4]:
mylist[6:]
Out[4]:
[0, 2, 4, 6, 8]
In [5]:
mylist[::2]
Out[5]:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [6]:
mylist[::-1]
Out[6]:
[7, 5, 3]
In [7]:
mylist[7:2:-2]
Out[7]:
In [8]:
matrix = [[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]
Get the second row by slicing twice
In [9]:
matrix[1][:]
Out[9]:
Try to get the second column by slicing. Do not use a list comprehension!
In [10]:
matrix[:][1]
Out[10]:
Import the NumPy package
In [11]:
import numpy as np
In [12]:
np.lookfor('create array')
In [13]:
help(np.array)
The variable matrix contains a list of lists. Turn it into an ndarray and assign it to the variable myarray. Verify that its type is correct.
In [14]:
myarray = np.array(matrix)
myarray
Out[14]:
In [15]:
type(myarray)
Out[15]:
For practicing purposes, arrays can conveniently be created with the arange method.
In [16]:
myarray1 = np.arange(6)
myarray1
Out[16]:
In [17]:
def array_attributes(a):
for attr in ('ndim', 'size', 'itemsize', 'dtype', 'shape', 'strides'):
print('{:8s}: {}'.format(attr, getattr(a, attr)))
In [18]:
array_attributes(myarray1)
Use np.array() to create arrays containing
and check the dtype attribute.
In [19]:
np.array([[1.0, 2.0], [3.0, 4.0]]).dtype
Out[19]:
In [20]:
np.array([[1+2j, 3+4j], [3-4j, 1-2j]]).dtype
Out[20]:
In [21]:
np.array([True, False]).dtype
Out[21]:
In [22]:
np.array(['Python', 'EuroSciPy', 'Erlangen']).dtype
Out[22]:
Do you understand what is happening in the following statement?
In [23]:
np.arange(1, 160, 10, dtype=np.int8)
Out[23]:
In [24]:
myarray2 = myarray1.reshape(2, 3)
myarray2
Out[24]:
In [25]:
array_attributes(myarray2)
In [26]:
myarray3 = myarray1.reshape(3, 2)
In [27]:
array_attributes(myarray3)
Set the first entry of myarray1 to a new value, e.g. 42.
In [28]:
myarray1[0] = 42
What happened to myarray2?
In [29]:
myarray2
Out[29]:
What happens when a matrix is transposed?
In [30]:
a = np.arange(9).reshape(3, 3)
a
Out[30]:
In [31]:
a.T
Out[31]:
Check the strides!
In [32]:
a.strides
Out[32]:
In [33]:
a.T.strides
Out[33]:
identical object
In [34]:
a = np.arange(4)
b = a
id(a), id(b)
Out[34]:
view: a different object working on the same data
In [35]:
b = a[:]
id(a), id(b)
Out[35]:
In [36]:
a[0] = 42
a, b
Out[36]:
an independent copy
In [37]:
a = np.arange(4)
b = np.copy(a)
id(a), id(b)
Out[37]:
In [38]:
a[0] = 42
a, b
Out[38]:
arange(start, stop, step), stop is not included in the array
In [39]:
np.arange(5, 30, 5)
Out[39]:
arange resembles range, but also works for floats
Create the array [1, 1.1, 1.2, 1.3, 1.4, 1.5]
In [40]:
np.arange(1, 1.55, 0.1)
Out[40]:
linspace(start, stop, num) determines the step to produce num equally spaced values, stop is included by default
Create the array [1., 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.]
In [41]:
np.linspace(1, 2, 11)
Out[41]:
For equally spaced values on a logarithmic scale, use logspace.
In [42]:
np.logspace(-2, 2, 5)
Out[42]:
In [43]:
np.logspace(0, 4, 9, base=2)
Out[43]:
In [44]:
import matplotlib.pyplot as plt
In [45]:
%matplotlib inline
In [46]:
x = np.linspace(0, 10, 100)
y = np.cos(x)
In [47]:
plt.plot(x, y)
Out[47]:
In [48]:
np.zeros((4, 4))
Out[48]:
Create a 4x4 array with integer zeros
In [49]:
np.zeros((4, 4), dtype=int)
Out[49]:
In [50]:
np.ones((2, 3, 3))
Out[50]:
Create a 3x3 array filled with tens
In [51]:
10*np.ones((3, 3))
Out[51]:
In [52]:
np.diag([1, 2, 3, 4])
Out[52]:
diag has an optional argument k. Try to find out what its effect is.
In [53]:
np.diag([1, 2, 3, 4], k=1)
Out[53]:
Replace the 1d array by a 2d array. What does diag do?
In [54]:
np.diag(np.arange(16).reshape(4, 4))
Out[54]:
In [55]:
np.info(np.eye)
Create the 3x3 array
[[2, 1, 0],
[1, 2, 1],
[0, 1, 2]]
In [56]:
2*np.eye(3)+np.eye(3, k=1)+np.eye(3, k=-1)
Out[56]:
In [57]:
np.random.rand(5, 2)
Out[57]:
In [58]:
np.random.seed(1234)
np.random.rand(5, 2)
Out[58]:
In [59]:
data = np.random.rand(20, 20)
plt.imshow(data, cmap=plt.cm.hot, interpolation='none')
plt.colorbar()
Out[59]:
In [60]:
casts = np.random.randint(1, 7, (100, 3))
plt.hist(casts, np.linspace(0.5, 6.5, 7))
Out[60]:
In [61]:
a = np.arange(10)
Create the array [7, 8, 9]
In [62]:
a[7:]
Out[62]:
Create the array [2, 4, 6, 8]
In [63]:
a[2::2]
Out[63]:
Create the array [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [64]:
a[::-1]
Out[64]:
In [65]:
a = np.arange(40).reshape(5, 8)
In [66]:
a[-3:, -3:]
Out[66]:
In [67]:
a[:, 3]
Out[67]:
In [68]:
a[1, 3:6]
Out[68]:
In [69]:
a[1::2, ::3]
Out[69]:
In [70]:
a = np.arange(40).reshape(5, 8)
In [71]:
a %3 == 0
Out[71]:
In [72]:
a[a %3 == 0]
Out[72]:
In [73]:
a[(1, 1, 2, 2, 3, 3), (3, 4, 2, 5, 3, 4)]
Out[73]:
In [74]:
nmax = 50
integers = np.arange(nmax)
is_prime = np.ones(nmax, dtype=bool)
is_prime[:2] = False
for j in range(2, int(np.sqrt(nmax))+1):
if is_prime[j]:
print(integers[is_prime])
is_prime[j*j::j] = False
print(integers[is_prime])
Create an array and calculate the sum over all elements
In [75]:
a = np.arange(9).reshape(3, 3)
a
Out[75]:
Now calculate the sum along axis 0 ...
In [76]:
np.sum(a, axis=0)
Out[76]:
and now along axis 1
In [77]:
np.sum(a, axis=1)
Out[77]:
Identify the axis in the following array
In [78]:
a = np.arange(24).reshape(2, 3, 4)
a
Out[78]:
In [79]:
np.sum(a, axis=0)
Out[79]:
In [80]:
np.sum(a, axis=1)
Out[80]:
In [81]:
np.sum(a, axis=2)
Out[81]:
Create a three-dimensional array
In [82]:
a = np.arange(24).reshape(2, 3, 4)
Produce a two-dimensional array by cutting along axis 0 ...
In [83]:
a[0, :, :]
Out[83]:
and axis 1 ...
In [84]:
a[:, 0, :]
Out[84]:
and axis 2
In [85]:
a[:, :, 0]
Out[85]:
What do you get by simply using the index [0]?
In [86]:
a[0]
Out[86]:
What do you get by using [..., 0]?
In [87]:
a[..., 0]
Out[87]:
In [88]:
a = np.arange(4)
b = np.arange(4, 8)
a, b
Out[88]:
In [89]:
a+b
Out[89]:
In [90]:
a*b
Out[90]:
Operations are elementwise. Check this by multiplying two 2d array...
In [91]:
a = np.arange(4).reshape(2, 2)
b = np.arange(4, 8).reshape(2, 2)
a, b
Out[91]:
In [92]:
a*b
Out[92]:
... and now do a real matrix multiplication
In [93]:
np.dot(a, b)
Out[93]:
In [94]:
a.dot(b)
Out[94]:
In [95]:
a @ b
Out[95]:
In [96]:
length_of_walk = 10000
realizations = 5
angles = 2*np.pi*np.random.rand(length_of_walk, realizations)
x = np.cumsum(np.cos(angles), axis=0)
y = np.cumsum(np.sin(angles), axis=0)
plt.plot(x, y)
plt.axis('scaled')
Out[96]:
In [97]:
plt.plot(np.hypot(x, y))
Out[97]:
In [98]:
plt.plot(np.mean(x**2+y**2, axis=1))
plt.axis('scaled')
Out[98]:
In [99]:
%%timeit a = np.arange(1000000)
a**2
In [100]:
%%timeit xvals = range(1000000)
[xval**2 for xval in xvals]
In [101]:
%%timeit a = np.arange(100000)
np.sin(a)
In [102]:
import math
In [103]:
%%timeit xvals = range(100000)
[math.sin(xval) for xval in xvals]
In [104]:
a = np.arange(12).reshape(3, 4)
a
Out[104]:
In [105]:
a+1
Out[105]:
In [106]:
a+np.arange(4)
Out[106]:
In [107]:
a+np.arange(3)
In [108]:
np.arange(3)
Out[108]:
In [109]:
np.arange(3).reshape(3, 1)
Out[109]:
In [110]:
a+np.arange(3).reshape(3, 1)
Out[110]:
In [111]:
%%timeit a = np.arange(10000).reshape(100, 100); b = np.ones((100, 100))
a+b
In [112]:
%%timeit a = np.arange(10000).reshape(100, 100)
a+1
Create a multiplication table for the numbers from 1 to 10 starting from two appropriately chosen 1d arrays.
In [113]:
np.arange(1, 11)*np.arange(1, 11).reshape(10, 1)
Out[113]:
As an alternative to reshape one can add additional axes with newaxes:
In [114]:
a = np.arange(5)
b = a[:, np.newaxis]
Check the shapes.
In [115]:
a.shape, b.shape
Out[115]:
In [116]:
x = np.linspace(-40, 40, 200)
y = x[:, np.newaxis]
z = np.sin(np.hypot(x-10, y))+np.sin(np.hypot(x+10, y))
plt.imshow(z, cmap='viridis')
Out[116]:
In [117]:
x, y = np.mgrid[-10:10:0.1, -10:10:0.1]
In [118]:
x
Out[118]:
In [119]:
y
Out[119]:
In [120]:
plt.imshow(np.sin(x*y))
Out[120]:
In [121]:
x, y = np.mgrid[-10:10:50j, -10:10:50j]
In [122]:
x
Out[122]:
In [123]:
y
Out[123]:
In [124]:
plt.imshow(np.arctan2(x, y))
Out[124]:
It is natural to use broadcasting. Check out what happens when you replace mgrid by ogrid.
In [125]:
x, y = np.ogrid[-10:10:0.1, -10:10:0.1]
In [126]:
x
Out[126]:
In [127]:
y
Out[127]:
In [128]:
plt.imshow(np.sin(x*y))
Out[128]:
In [129]:
x, y = np.ogrid[-10:10:50j, -10:10:50j]
In [130]:
x
Out[130]:
In [131]:
y
Out[131]:
In [132]:
plt.imshow(np.arctan2(x, y))
Out[132]:
In [133]:
npts = 300
y, x = np.ogrid[-1.5:1.5:300j, -2:1:300j]
c = x+1j*y
z = c
for n in range(50):
z = z**2+c
imdata = (np.abs(z) < 50)
print(imdata.shape)
plt.imshow(imdata, cmap='gray')
Out[133]:
Create an array of random numbers and determine the fraction of points with distance from the origin smaller than one. Determine an approximation for π.
In [134]:
npts = 1000000
pts = np.random.rand(2*npts).reshape(2, -1)
4*np.count_nonzero(np.hypot(pts[0], pts[1]) < 1)/npts
Out[134]:
In [135]:
import numpy.linalg as LA
In [136]:
a = np.arange(4).reshape(2, 2)
eigenvalues, eigenvectors = LA.eig(a)
eigenvalues
Out[136]:
In [137]:
eigenvectors
Out[137]:
Explore whether the eigenvectors are the rows or the columns.
In [138]:
a @ eigenvectors[:, 0]
Out[138]:
In [139]:
eigenvalues[0]*eigenvectors[:, 0]
Out[139]:
Try out eigvals and other methods offered by linalg which your are interested in
In [ ]:
In [ ]:
In [ ]:
Determine the eigenvalue larger than one appearing in the Fibonacci problem. Verify the result by calculating the ratio of successive Fibonacci numbers. Do you recognize the result?
In [140]:
LA.eigvals(np.array([[1, 1], [1, 0]]))
Out[140]:
In [141]:
fnp1, fn = 1, 1
for n in range(20):
fnp1, fn = fnp1+fn, fnp1
print(fnp1/fn)
np.random.choice
In [142]:
stories = 10
length = 1000
jumps = np.random.choice(np.array([-1, 1]), (stories, length))
positions = np.cumsum(jumps, axis=1)
In [143]:
plt.plot(positions.T)
Out[143]:
In [144]:
plt.plot(np.mean(positions, axis=0))
Out[144]:
In [145]:
plt.plot(np.var(positions, axis=0))
Out[145]:
Create a 2d array containing random numbers and generate a vector containing for each row the entry closest to one-half.
In [146]:
a = np.random.rand(20).reshape(4, 5)
a
Out[146]:
In [147]:
a[np.arange(4), np.argsort(np.abs(a-0.5), axis=1)[:, 0]]
Out[147]:
In [148]:
from numpy.polynomial import polynomial as P
Powers increase from left to right (index corresponds to power)
In [149]:
p1 = P.Polynomial([1, 2])
In [150]:
p1.degree()
Out[150]:
In [151]:
p1.roots()
Out[151]:
In [152]:
p4 = P.Polynomial([24, -50, 35, -10, 1])
In [153]:
p4.degree()
Out[153]:
In [154]:
p4.roots()
Out[154]:
In [155]:
p4.deriv()
Out[155]:
In [156]:
p4.integ()
Out[156]:
In [157]:
P.polydiv(p4.coef, p1.coef)
Out[157]:
In [158]:
x = np.linspace(0, np.pi, 100)
y = np.sin(x)+0.2*np.random.rand(100)
plt.plot(x, y, 'o')
fit = P.Polynomial(P.polyfit(x, y, 2))
plt.plot(x, fit(x))
Out[158]:
In [159]:
from scipy import misc
face = misc.face(gray=True)
face
Out[159]:
In [160]:
plt.imshow(face, cmap=plt.cm.gray)
Out[160]:
Modify this image, e.g. convert it to a black and white image, put a black frame, change the contrast, ...
In [161]:
plt.imshow(face > 128, cmap=plt.cm.gray)
Out[161]:
In [162]:
framedface = np.zeros_like(face)
framedface[30:-31, 30:-31] = face[30:-31, 30:-31]
plt.imshow(framedface, cmap=plt.cm.gray)
Out[162]:
In [163]:
plt.imshow(255*(face/255)**1.5, cmap=plt.cm.gray)
Out[163]:
In [164]:
sy, sx = face.shape
y, x = np.ogrid[:sy, :sx]
centerx, centery = 660, 300
mask = ((y - centery)**2 + (x - centerx)**2) > 230**2
face[mask] = 0
plt.imshow(face, cmap=plt.cm.gray)
Out[164]: