2.6. Solutions: Lecture 2#
2.6.1. Exercise 2.1#
ex_2.1.py
#!/usr/bin/python3
"""Create one-dimensional NumPy arrays using different generation techniques
"""
import numpy as np
def main():
# Creating an array from a list
a = np.array([1, 2, 3, 4, 5])
print("np.array([1, 2, 3, 4, 5] = ", a)
# Creating an array from a tuple
b = np.array((1, 2, 3, 4, 5))
print("np.array((1, 2, 3, 4, 5)) = ", b)
# Creating an array using the arange function
c = np.arange(1, 6)
print("np.arange(1, 6) = ", c)
# Creating an array using the linspace function
d = np.linspace(1, 5, 5)
print("np.linspace(1, 5, 5) = ", d)
# Creating an array using the logspace function
e = np.logspace(1, 5, 5)
print("np.logspace(1, 5, 5) = ", e)
# Creating an array of zeros
f = np.zeros(5)
print("np.zeros(5) = ", f)
# Creating an array of ones
g = np.ones(5)
print("np.ones(5) = ", g)
# Creating an empty array
h = np.empty(5)
print("np.empty(5) = ", h)
return
if __name__ == "__main__":
main()
2.6.2. Exercise 2.2#
ex_2.2.py
#!/usr/bin/python3
"""
Create a one-dimentional NumPy array containing a sequence of integer numbers from 1 to 100.
Starting from this, create a one-dimensional NumPy array containing in each entry the sum of
integer numbers from 1 until the index of that entry
"""
import numpy as np
def main():
# Creating an array using the arange function
a = np.arange(1,101)
print('Array of integer numbers from 1 to 100:\n', a)
# Creating an array containing the sum of integer numbers from 1 until the index of that entry
b = np.cumsum(a)
print('Array containing the sum of integer numbers from 1 until the index of that entry:\n', b)
return
if __name__ == '__main__':
main()
2.6.3. Exercise 2.3#
ex_2.3.py
#!/usr/bin/python3
"""
Create a one-dimensional array containing the sequence of the first 50 even natural numbers
Create a one-dimensional array containing the sequence of the first 50 odd natural numbers
Create a one-dimensional array containing the element-wise sum of the previous two arrays
"""
import numpy as np
def main():
# Creating an array containing the sequence of the first 50 even natural numbers
a_even = np.arange(2, 101, 2)
print('Array of the first 50 even natural numbers:\n', a_even, '\n')
# Creating an array containing the sequence of the first 50 odd natural numbers
a_odd = np.arange(1, 100, 2)
print('Array of the first 50 odd natural numbers:\n', a_odd, '\n')
# Creating an array containing the element-wise sum of the previous two arrays
a_sum = a_even + a_odd
print('Array containing the element-wise sum of the previous two arrays:\n', a_sum, '\n')
return
if __name__ == '__main__':
main()
2.6.4. Exercise 2.4#
ex_2.4.py
#!/usr/bin/python3
"""
Compare the time performances of element-wise operations performed between two lists
with respect to the same operation performed in compact form between two NumPy arrays
After which size the differences start being significant?
"""
import numpy as np
import time
def main():
for N in np.logspace(1,6,6):
listA = list(range(int(N)))
listB = list(range(int(N)))
listA_np = np.array(listA)
listB_np = np.array(listB)
start = time.time()
listC = [a*b for a,b in zip(listA,listB)]
end = time.time()
start_np = time.time()
listC_np = listA_np * listB_np
end_np = time.time()
print(f"N = {N}: time(list) = {1000.*(end-start):.3f}ms, time(ndarray) = {1000.*(end_np-start_np):.3f}ms")
return
if __name__ == '__main__':
main()
2.6.5. Exercise 2.5#
ex_2.5.py
#!/usr/bin/python3
"""
After finding how the `numpy.sort` function works,
write a Python library containing a function that determines the median of an array.
Write a main program that tests the performance of the developed function.
"""
import numpy as np
from statistics import median
def main():
a = np.array([2,5,6,2,6,3,5,3,6,8,1,2,3,9,10,2,3,5,2,6,23,4,75,371,82,1])
a_median = median(a)
print(f'Median of the array a: {a_median}')
print(f'n.b.: sorted array is\n{np.sort(a)}')
return
if __name__ == '__main__':
main()
statistics.py
"""
A module that contains functions for statistical analysis.
"""
import numpy as np
def median(x):
"""A function that determines the median of an array.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the median of the array
"""
x_sorted = np.sort(x)
if len(x_sorted)%2 == 0:
# even number of elements - returns the average of the two central elements
m = (x_sorted[int(len(x_sorted)/2)-1] + x_sorted[int(len(x_sorted)/2)])/2
else:
# odd number of elements - returns the central element
m = x_sorted[int((len(x_sorted)-1)/2)]
return m
def percentile75(x):
"""A function that determines the value above which lies the 25% of the values.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the value above which lies the 25% of the values
"""
x_sorted = np.sort(x)
idx = int(0.75*len(x))
pv = x_sorted[idx]
return pv
def percentile25(x):
"""A function that determines the value above which lies the 25% of the values.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the value above which lies the 25% of the values
"""
x_sorted = np.sort(x)
idx = int(0.25*len(x))
pv = x_sorted[idx]
return pv
def percentile(x,p):
"""A function that determines the value above which lies the a certain fraction of the values.
Args:
x (numpy.ndarray): the array for which the percentile is to be calculated
p (float): the fraction of the values (should be whithin [0,1])
Returns:
float: the value above which lies the fraction `p` of the values
"""
if not (0 < p and p < 1):
raise ValueError(f'The percentile value p = {p} is not within the range [0,1]')
x_sorted = np.sort(x)
idx = int(p*len(x))
pv = x_sorted[idx]
return pv
def mean(x):
"""A function that calculates the mean of an array.
Args:
x (numpy.ndarray): the array for which the mean is to be calculated
Returns:
float: the mean of the array
"""
m = np.sum(x)/len(x)
return m
def variance(x):
"""A function that calculates the variance of an array.
Args:
x (numpy.ndarray): the array for which the variance is to be calculated
Returns:
float: the variance of the array
"""
m = mean(x)
m2= mean(x*x)
return m2-m*m
def stdev(x,bessel=True):
"""A function that calculates the standard deviation of an array.
Args:
x (numpy.ndarray): the array for which the standard deviation is to be calculated
bessel (bool, optional): applies Bessel's correction. Defaults to True.
Returns:
float: the standard deviation of the array
"""
m = mean(x)
r = x-m
s = np.sqrt( np.sum(r*r)/(len(x)-1) ) if bessel else np.sqrt( np.sum(r*r)/len(x) )
return s
def stdev_mean(x,bessel=True):
"""A function that calculates the standard deviation of the mean of an array.
Args:
x (numpy.ndarray): the array for which the standard deviation of the mean is to be calculated
bessel (bool, optional): applies Bessel's correction. Defaults to True.
Returns:
float: the standard deviation of the mean of the array
"""
s = stdev(x,bessel)
return s/np.sqrt(len(x))
2.6.6. Exercise 2.6#
ex_2.6.py
"""
Given an array of numbers, write a Python library containing a function
which determines the the value below which lies the 25% of the values,
and the one above which lies the 25% of the the values
Generalise the function to the case where the percentage of tails is set as input value
"""
import numpy as np
from statistics import percentile25, percentile75, percentile
def main():
a = np.array([2,5,6,2,6,3,5,3,6,8,1,2,3,9,10,2,3,5,2,6,23,4,75,371,82,1])
a_75 = percentile75(a)
print(f'The 75% percentile of the array a: {a_75}')
a_25 = percentile25(a)
print(f'The 25% percentile of the array a: {a_25}')
p = 0.4
a_p = percentile(a,p)
print(f'The {100.*p:.1f}% percentile of the array a: {a_p}')
print(f'n.b.: sorted array is\n{np.sort(a)}')
return
if __name__ == '__main__':
main()
statistics.py
"""
A module that contains functions for statistical analysis.
"""
import numpy as np
def median(x):
"""A function that determines the median of an array.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the median of the array
"""
x_sorted = np.sort(x)
if len(x_sorted)%2 == 0:
# even number of elements - returns the average of the two central elements
m = (x_sorted[int(len(x_sorted)/2)-1] + x_sorted[int(len(x_sorted)/2)])/2
else:
# odd number of elements - returns the central element
m = x_sorted[int((len(x_sorted)-1)/2)]
return m
def percentile75(x):
"""A function that determines the value above which lies the 25% of the values.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the value above which lies the 25% of the values
"""
x_sorted = np.sort(x)
idx = int(0.75*len(x))
pv = x_sorted[idx]
return pv
def percentile25(x):
"""A function that determines the value above which lies the 25% of the values.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the value above which lies the 25% of the values
"""
x_sorted = np.sort(x)
idx = int(0.25*len(x))
pv = x_sorted[idx]
return pv
def percentile(x,p):
"""A function that determines the value above which lies the a certain fraction of the values.
Args:
x (numpy.ndarray): the array for which the percentile is to be calculated
p (float): the fraction of the values (should be whithin [0,1])
Returns:
float: the value above which lies the fraction `p` of the values
"""
if not (0 < p and p < 1):
raise ValueError(f'The percentile value p = {p} is not within the range [0,1]')
x_sorted = np.sort(x)
idx = int(p*len(x))
pv = x_sorted[idx]
return pv
def mean(x):
"""A function that calculates the mean of an array.
Args:
x (numpy.ndarray): the array for which the mean is to be calculated
Returns:
float: the mean of the array
"""
m = np.sum(x)/len(x)
return m
def variance(x):
"""A function that calculates the variance of an array.
Args:
x (numpy.ndarray): the array for which the variance is to be calculated
Returns:
float: the variance of the array
"""
m = mean(x)
m2= mean(x*x)
return m2-m*m
def stdev(x,bessel=True):
"""A function that calculates the standard deviation of an array.
Args:
x (numpy.ndarray): the array for which the standard deviation is to be calculated
bessel (bool, optional): applies Bessel's correction. Defaults to True.
Returns:
float: the standard deviation of the array
"""
m = mean(x)
r = x-m
s = np.sqrt( np.sum(r*r)/(len(x)-1) ) if bessel else np.sqrt( np.sum(r*r)/len(x) )
return s
def stdev_mean(x,bessel=True):
"""A function that calculates the standard deviation of the mean of an array.
Args:
x (numpy.ndarray): the array for which the standard deviation of the mean is to be calculated
bessel (bool, optional): applies Bessel's correction. Defaults to True.
Returns:
float: the standard deviation of the mean of the array
"""
s = stdev(x,bessel)
return s/np.sqrt(len(x))
2.6.7. Exercise 2.7#
ex_2.7.py
#!/usr/bin/python3
"""
Write a Python library containing functions to perform the following operations
for NumPy 1D arrays:
* Calculate the mean of its elements
* Calculate the variance of its elements
* Calculate the standard deviation of its elements
* Calculate the standard deviation from the mean of its elements
"""
import numpy as np
from statistics import mean, variance, stdev, stdev_mean
def main():
a = np.array([5,2,1,5,2,3,4,6,2,8,4,5,7,6,8,9,1])
a_mean = mean(a)
print(f'Mean of the array a: {a_mean:.2f}')
a_var = variance(a)
print(f'Variance of the array a: {a_var:.2f}')
a_stdev = stdev(a)
print(f'Standard deviation of the array a: {a_stdev:.2f}')
a_stdev_mean = stdev_mean(a)
print(f'Standard deviation from the mean of the array a: {a_stdev_mean:.2f}')
return
if __name__ == '__main__':
main()
statistics.py
"""
A module that contains functions for statistical analysis.
"""
import numpy as np
def median(x):
"""A function that determines the median of an array.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the median of the array
"""
x_sorted = np.sort(x)
if len(x_sorted)%2 == 0:
# even number of elements - returns the average of the two central elements
m = (x_sorted[int(len(x_sorted)/2)-1] + x_sorted[int(len(x_sorted)/2)])/2
else:
# odd number of elements - returns the central element
m = x_sorted[int((len(x_sorted)-1)/2)]
return m
def percentile75(x):
"""A function that determines the value above which lies the 25% of the values.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the value above which lies the 25% of the values
"""
x_sorted = np.sort(x)
idx = int(0.75*len(x))
pv = x_sorted[idx]
return pv
def percentile25(x):
"""A function that determines the value above which lies the 25% of the values.
Args:
x (numpy.ndarray): the array for which the median is to be calculated
Returns:
float: the value above which lies the 25% of the values
"""
x_sorted = np.sort(x)
idx = int(0.25*len(x))
pv = x_sorted[idx]
return pv
def percentile(x,p):
"""A function that determines the value above which lies the a certain fraction of the values.
Args:
x (numpy.ndarray): the array for which the percentile is to be calculated
p (float): the fraction of the values (should be whithin [0,1])
Returns:
float: the value above which lies the fraction `p` of the values
"""
if not (0 < p and p < 1):
raise ValueError(f'The percentile value p = {p} is not within the range [0,1]')
x_sorted = np.sort(x)
idx = int(p*len(x))
pv = x_sorted[idx]
return pv
def mean(x):
"""A function that calculates the mean of an array.
Args:
x (numpy.ndarray): the array for which the mean is to be calculated
Returns:
float: the mean of the array
"""
m = np.sum(x)/len(x)
return m
def variance(x):
"""A function that calculates the variance of an array.
Args:
x (numpy.ndarray): the array for which the variance is to be calculated
Returns:
float: the variance of the array
"""
m = mean(x)
m2= mean(x*x)
return m2-m*m
def stdev(x,bessel=True):
"""A function that calculates the standard deviation of an array.
Args:
x (numpy.ndarray): the array for which the standard deviation is to be calculated
bessel (bool, optional): applies Bessel's correction. Defaults to True.
Returns:
float: the standard deviation of the array
"""
m = mean(x)
r = x-m
s = np.sqrt( np.sum(r*r)/(len(x)-1) ) if bessel else np.sqrt( np.sum(r*r)/len(x) )
return s
def stdev_mean(x,bessel=True):
"""A function that calculates the standard deviation of the mean of an array.
Args:
x (numpy.ndarray): the array for which the standard deviation of the mean is to be calculated
bessel (bool, optional): applies Bessel's correction. Defaults to True.
Returns:
float: the standard deviation of the mean of the array
"""
s = stdev(x,bessel)
return s/np.sqrt(len(x))
2.6.8. Exercise 2.8#
ex_2.8.py
#!/usr/bin/python3
"""
Write a program that draws the basic trigonometric functions over a meaningful domain,
using NumPy universal functions
* Show that the sine and cosine functions differ by a phase
* Show that the terms *A* and *B* in the equation $f(x) = \sin (x-A) + B$ represent
horizontal and vertical translations of the functional form, respectively
* Show that the terms *C* and *D* in the equation $f(x) = D \cos (Cx)$ represent
horizontal and vertical dilations of the functional form, respectivey
"""
import numpy as np
import matplotlib.pyplot as plt
def f(x, A, B):
"""A function that adds a phase to the sine function and translates it vertically
Args:
x (array_like): the value(s) of the independent variable
A (float): the negative phase of the sine function
B (float): the shift of the sine function along the y-axis
Returns:
numpy.ndarray: the value(s) of the dependent variable
"""
y = np.sin(x - A) + B
return y
def g(x, C, D):
"""A function that amplifies the cosine function and modifies its pulse
Args:
x (array_like): the value(s) of the independent variable
C (float): the pulse of the cosine function
D (float): the amplitude of the cosine function
Returns:
numpy.ndarray: the value(s) of the dependent variable
"""
y = D * np.cos(C * x)
return y
def main():
# Creating an array using the linspace function
x = np.linspace(0,2*np.pi,10_000)
# Creating an array containing the sin of x
sinx = np.sin(x)
# Creating an array containing the cos of x
cosx = np.cos(x)
# Plot the trigonometric functions
fig, ax = plt.subplots(nrows=1,ncols=1)
ax.plot(x,sinx,label='sin(x)')
ax.plot(x,cosx,label='cos(x)')
ax.set_title('Trigonometric functions')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()
fig.savefig('trigonometric_functions.png',dpi=300)
# Show that A and B in f(x,A,B) represent horizontal and vertical translations
fig, ax = plt.subplots(nrows=1,ncols=1)
ax.plot(x,sinx,label='sin(x)')
A, B = np.pi/3, 1
ax.plot(x,f(x,A,B),label=f'sin(x-{A:.1f})+{B:.1f}')
ax.set_title('Translation of the sine function')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()
fig.savefig('trigonometric_functions_translations.png',dpi=300)
# Show that C and D in g(x,C,D) represent horizontal and vertical dilations
fig, ax = plt.subplots(nrows=1,ncols=1)
ax.plot(x,cosx,label='cos(x)')
C, D = 2, 2
ax.plot(x,g(x,C,D),label=f'{D:.1f}cos({C:.1f}x)')
ax.set_title('Dilation of the cosine function')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()
fig.savefig('trigonometric_functions_dilations.png',dpi=300)
plt.show()
return
if __name__ == '__main__':
main()
2.6.9. Exercise 2.9#
ex_2.9.py
#!/usr/bin/python3
'''
Write a program that draws the Mandelbrot set with matplotlib.
'''
import matplotlib.pyplot as plt
import numpy as np
def check_if_limited (compl_start, num = 100) :
number = complex (0.0)
for i in range (num) :
number = number ** 2 + compl_start
if abs (number) > 2 :
return False
return True
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main():
xmin = -2.
xmax = 1.
ymin = -2.
ymax = 2.
resolution = 0.03
x_coord = np.arange (xmin, xmax, resolution)
y_coord = np.arange (ymin, ymax, resolution)
fig, ax = plt.subplots (nrows = 1, ncols = 1)
ix = 0
for x in x_coord :
iy = 0
for y in y_coord :
if check_if_limited (complex (x, y)) :
ax.plot (x, y, marker='o', color = 'black')
else :
ax.plot (x, y, marker='o', color = 'white')
iy = iy + 1
ix = ix + 1
fig.savefig ('mandel.png',dpi=300)
plt.show ()
return
if __name__ == '__main__':
main()