import copy import numpy as np from matplotlib import pyplot as plt # Task 1.1 def mult_scalar(A, c): """ Returns a new matrix created by multiplying elements of matrix A by a scalar c. """ return [[i * c for i in row] for row in A] # Test case for Task 1.1 def test_11(): A = [[5, 7, 9], [1, 4, 3]] A_copy = copy.deepcopy(A) actual = mult_scalar(A_copy, 2) expected = [[10, 14, 18], [2, 8, 6]] assert(A == A_copy) # check for aliasing assert(actual == expected) A2 = [[6, 5, 5], [8, 6, 0], [1, 5, 8]] A2_copy = copy.deepcopy(A2) actual2 = mult_scalar(A2_copy, 5) expected2 = [[30, 25, 25], [40, 30, 0], [5, 25, 40]] assert(A2 == A2_copy) # check for aliasing assert(actual2 == expected2) # test_11() # Task 1.2 def add_matrices(A, B): """ Returns a new matrix that is the result of adding matrix B to matrix A. """ if len(A) != len(B) or len(A[0]) != len(B[0]): raise Exception('A and B cannot be added as they have incompatible dimensions!') result = [[0] * len(A[0]) for _ in A] for i in range(len(A)): for j in range(len(A[0])): result[i][j] = A[i][j] + B[i][j] return result # Test case for Task 1.2 def test_12(): A = [[5, 7, 9], [1, 4, 3]] B = [[2, 3, 4], [5, 6, 7]] A_copy = copy.deepcopy(A) B_copy = copy.deepcopy(B) actual = add_matrices(A_copy, B_copy) expected = [[7, 10, 13], [6, 10, 10]] assert(A == A_copy) # check for aliasing assert(B == B_copy) # check for aliasing assert(actual == expected) #test_12() # Task 1.3 def transpose_matrix(A): """ Returns a new matrix that is the transpose of matrix A. """ # return list([list(a) for a in zip(*A)]) rows = len(A) cols = len(A[0]) result = [[0] * rows for _ in range(cols)] for i in range(cols): for j in range(rows): result[i][j] = A[j][i] return result # Test case for Task 1.3 def test_13(): A = [[5, 7, 9], [1, 4, 3]] A_copy = copy.deepcopy(A) actual = transpose_matrix(A_copy) expected = [[5, 1], [7, 4], [9, 3]] assert(A == A_copy) assert(actual == expected) #test_13() # Task 1.4 def dot_prod(A, B): if len(A) != len(B): raise Exception('A and B cannot be multiplied as they have incompatible dimensions!') return sum([A[i] * B[i] for i in range(len(A))]) def mult_matrices(A, B): """ Multiplies matrix A by matrix B, giving AB. Note ---- Do not use numpy for this question. """ if len(A[0]) != len(B): raise Exception('Incompatible dimensions for matrix multiplication of A and B') res_rows = len(A) res_cols = len(B[0]) result = [[0] * res_cols for _ in range(res_rows)] trans_B = transpose_matrix(B) for i in range(res_rows): for j in range(res_cols): result[i][j] = dot_prod(A[i], trans_B[j]) return result # Test Case for Task 1.4 def test_14(): A = [[5, 7, 9], [1, 4, 3]] B = [[2, 5], [3, 6], [4, 7]] A_copy = copy.deepcopy(A) B_copy = copy.deepcopy(B) actual = mult_matrices(A, B) expected = [[67, 130], [26, 50]] assert(A == A_copy and B == B_copy) assert(actual == expected) A2 = [[-13, -10], [-24, 14]] B2 = [[1, 0], [0, 1]] A2_copy = copy.deepcopy(A2) B2_copy = copy.deepcopy(B2) actual2 = mult_matrices(A2, B2) expected2 = [[-13, -10], [-24, 14]] assert(A2 == A2_copy and B2 == B2_copy) assert(actual2 == expected2) # test_14() # Task 1.5 def invert_matrix(A): """ Returns the inverse of matrix A, if it exists; otherwise, returns False """ if len(A[0]) != len(A): return False A_len = len(A) result = copy.deepcopy(A) # Step 0 for i in range(A_len): result[i].extend([0] * A_len) result[i][i + A_len] = 1 result = [[float(i) for i in row] for row in result] # Step 1 for i in range(A_len): # Step 1 for k in range(i, A_len): if result[k][i] != 0: break if result[k][i] == 0: return False result[i], result[k] = result[k], result[i] # Step 2 scalar = 1 / result[i][i] result[i] = [scalar * x for x in result[i]] # Step 3: Add multiples of the new ith row to all other rows such that the value in their ith column becomes 0 for k in range(A_len): if k == i: continue scalar = -result[k][i] result[k] = [result[k][j] + scalar * result[i][j] for j in range(2 * A_len)] for i in range(A_len): result[i] = result[i][A_len:] return result # Test case for Task 1.5 def test_15(): A = [[1, 0 ,0], [0, 1, 0], [0, -4, 1]] A_copy = copy.deepcopy(A) actual = invert_matrix(A) expected = [[1, 0 ,0], [0, 1, 0], [0, 4, 1]] assert(A == A_copy) for i in range(len(A)): for j in range(len(A[0])): assert(round(actual[i][j], 11) == round(expected[i][j], 11)) A2 = [[0, 3, 2], [0, 0, 1], [1, 5, 3]] A2_copy = copy.deepcopy(A2) actual2 = invert_matrix(A2) expected2 = [[-5/3, 1/3 ,1], [1/3, -2/3, 0], [0, 1, 0]] assert(A2 == A2_copy) for i in range(len(A2)): for j in range(len(A2[0])): assert(round(actual2[i][j], 11) == round(expected2[i][j], 11)) A3 = [[1, 0, 0], [0, 1, 0], [0, 0, 0]] # non-invertible matrix actual3 = invert_matrix(A3) expected3 = False assert actual3 == expected3 test_15() from prepare_data import * # Example on loading the data for Task 2 from prepare_data import * # loads the `get_...` helper funtions df = get_data() cases_cumulative = get_n_cases_cumulative(df) deaths_cumulative = get_n_deaths_cumulative(df) healthcare_spending = get_healthcare_spending(df) mask_prices = get_mask_prices(healthcare_spending.shape[1]) stringency_values = get_stringency_values(df) cases_top_cumulative = get_n_cases_top_cumulative(df) # Task 2.1 def compute_death_rate_first_n_days(n, cases_cumulative, deaths_cumulative): ''' Computes the average number of deaths recorded for every confirmed case that is recorded from the first day to the nth day (inclusive). Parameters ---------- n: int How many days of data to return in the final array. cases_cumulative: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the cumulative number of confirmed cases in that country, i.e. the ith row of `cases_cumulative` contains the data of the ith country, and the (i, j) entry of `cases_cumulative` is the cumulative number of confirmed cases on the (j + 1)th day in the ith country. deaths_cumulative: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the cumulative number of confirmed deaths (as a result of COVID-19) in that country, i.e. the ith row of `deaths_cumulative` contains the data of the ith country, and the (i, j) entry of `deaths_cumulative` is the cumulative number of confirmed deaths on the (j + 1)th day in the ith country. Returns ------- Average number of deaths recorded for every confirmed case from the first day to the nth day (inclusive) for each country as a 1D `ndarray` such that the entry in the ith row corresponds to the death rate in the ith country as represented in `cases_cumulative` and `deaths_cumulative`. Note ---- `cases_cumulative` and `deaths_cumulative` are such that the ith row in the former and that in the latter contain data of the same country. In addition, if there are no confirmed cases for a particular country, the expected death rate for that country should be zero. (Hint: to deal with NaN look at `np.nan_to_num`) ''' return np.nan_to_num(deaths_cumulative[:, n - 1] / cases_cumulative[:, n - 1]) # Test case for Task 2.1 def test_21(): n_cases_cumulative = cases_cumulative[:3, :] #Using data from CSV. Make sure to run relevant cell above n_deaths_cumulative = deaths_cumulative[:3, :] expected = np.array([0.0337837838, 0.0562347188, 0.1410564226]) np.testing.assert_allclose(compute_death_rate_first_n_days(100, n_cases_cumulative, n_deaths_cumulative), expected) sample_cumulative = np.array([[1,2,3,4,8,8,10,10,10,10], [1,2,3,4,8,8,10,10,10,10]]) sample_death = np.array([[0,0,0,1,2,2,2,2,5,5], [0,0,0,1,2,2,2,2,5,5]]) expected2 = np.array([0.5, 0.5]) assert(np.all(compute_death_rate_first_n_days(10, sample_cumulative, sample_death) == expected2)) sample_cumulative2 = np.array([[1,2,3,4,8,8,10,10,10,10]]) sample_death2 = np.array([[0,0,0,1,2,2,2,2,5,5]]) expected3 = np.array([0.5]) assert(compute_death_rate_first_n_days(10, sample_cumulative2, sample_death2) == expected3) expected4 = np.array([0.25]) assert(compute_death_rate_first_n_days(5, sample_cumulative2, sample_death2) == expected4) #test_21() # Task 2.2 def compute_increase_in_cases(n, cases_cumulative): ''' Computes the daily increase in confirmed cases for each country for the first n days, starting from the first day. Parameters ---------- n: int How many days of data to return in the final array. If the input data has fewer than n days of data then we just return whatever we have for each country up to n. cases_cumulative: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the cumulative number of confirmed cases in that country, i.e. the ith row of `cases_cumulative` contains the data of the ith country, and the (i, j) entry of `cases_cumulative` is the cumulative number of confirmed cases on the (j + 1)th day in the ith country. Returns ------- Daily increase in cases for each country as a 2D `ndarray` such that the (i, j) entry corresponds to the increase in confirmed cases in the ith country on the (j + 1)th day, where j is non-negative. Note ---- The number of cases on the zeroth day is assumed to be 0, and we want to compute the daily increase in cases starting from the first day. ''' result = np.diff(cases_cumulative[:, :n], axis=-1, prepend=0) return result # compute_increase_in_cases(4, np.array([[1, 3, 6, 10], [0, 5, 6, 8]])) # Test case for Task 2.2 def test_22():# cases_cumulative = np.zeros((100, 20)) cases_cumulative[:, :] = np.arange(1, 21) actual = compute_increase_in_cases(100, cases_cumulative) assert(np.all(actual == np.ones((100, 20)))) sample_cumulative = np.array([[1,2,3,4,8,8,10,10,10,10],[1,1,3,5,8,10,15,20,25,30]]) expected = np.array([[1, 1, 1, 1, 4.], [1, 0, 2, 2, 3]]) assert(np.all(compute_increase_in_cases(5,sample_cumulative) == expected)) expected2 = np.array([[1, 1, 1, 1, 4, 0, 2, 0, 0, 0],[1, 0, 2, 2, 3, 2, 5, 5, 5, 5]]) assert(np.all(compute_increase_in_cases(10,sample_cumulative) == expected2)) assert(np.all(compute_increase_in_cases(20,sample_cumulative) == expected2)) sample_cumulative2 = np.array([[51764, 51848, 52007, 52147, 52330, 52330],\ [55755, 56254, 56572, 57146, 57727, 58316],\ [97857, 98249, 98631, 98988, 99311, 99610]]) expected3 = np.array([\ [51764, 84, 159, 140, 183, 0],\ [55755, 499, 318, 574, 581, 589],\ [97857, 392, 382, 357, 323, 299]]) assert(np.all(compute_increase_in_cases(6,sample_cumulative2) == expected3)) test_22() # Task 2.3 def find_max_increase_in_cases(n_cases_increase): ''' Finds the maximum daily increase in confirmed cases for each country. Parameters ---------- n_cases_increase: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the daily increase in the number of confirmed cases in that country, i.e. the ith row of `n_cases_increase` contains the data of the ith country, and the (i, j) entry of `n_cases_increase` is the daily increase in the number of confirmed cases on the (j + 1)th day in the ith country. Returns ------- Maximum daily increase in cases for each country as a 1D `ndarray` such that the ith entry corresponds to the increase in confirmed cases in the ith country as represented in `n_cases_increase`. ''' return np.max(n_cases_increase, axis=1) # Test case for Task 2.3 def test_23(): n_cases_increase = np.ones((100, 20)) actual = find_max_increase_in_cases(n_cases_increase) expected = np.ones(100) assert(np.all(actual == expected)) sample_increase = np.array([[1,2,3,4,8,8,10,10,10,10],[1,1,3,5,8,10,15,20,25,30]]) expected2 = np.array([10, 30]) # max of [1,2,3,4,8,8,10,10,10,10] => 10, max of [1,1,3,5,8,10,15,20,25,30] => 30 assert(np.all(find_max_increase_in_cases(sample_increase) == expected2)) sample_increase2 = np.array([\ [51764, 84, 159, 140, 183, 0],\ [55755, 499, 318, 574, 581, 589],\ [97857, 392, 382, 357, 323, 299]]) expected3 = np.array([51764, 55755, 97857]) assert(np.all(find_max_increase_in_cases(sample_increase2) == expected3)) n_cases_increase2 = compute_increase_in_cases(cases_top_cumulative.shape[1], cases_top_cumulative) expected4 = np.array([ 68699., 97894., 258110.]) assert(np.all(find_max_increase_in_cases(n_cases_increase2) == expected4)) test_23() # Task 2.4 def compute_n_masks_purchaseable(healthcare_spending, mask_prices): ''' Computes the total number of masks that each country can purchase if she spends all her emergency healthcare spending on masks. Parameters ---------- healthcare_spending: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the emergency healthcare spending made by that country, i.e. the ith row of `healthcare_spending` contains the data of the ith country, and the (i, j) entry of `healthcare_spending` is the amount which the ith country spent on healthcare on (j + 1)th day. mask_prices: np.ndarray 1D `ndarray` such that the jth entry represents the cost of 100 masks on the (j + 1)th day. Returns ------- Total number of masks which each country can purchase as a 1D `ndarray` such that the ith entry corresponds to the total number of masks purchaseable by the ith country as represented in `healthcare_spending`. Note ---- The masks can only be bought in batches of 100s. ''' return np.sum(np.floor(healthcare_spending/mask_prices)* 100, axis=1) # Test case for Task 2.4 def test_24(): prices_constant = np.ones(5) healthcare_spending_constant = np.ones((7, 5)) actual = compute_n_masks_purchaseable(healthcare_spending_constant, prices_constant) expected = np.ones(7) * 500 assert(np.all(actual == expected)) healthcare_spending1 = healthcare_spending[:3, :] #Using data from CSV expected2 = [3068779300, 378333500, 6208321700] assert(np.all(compute_n_masks_purchaseable(healthcare_spending1, mask_prices)==expected2)) healthcare_spending2 = np.array([[0, 100, 0], [100, 0, 200]]) mask_prices2 = np.array([4, 3, 20]) expected3 = np.array([3300, 3500]) assert(np.all(compute_n_masks_purchaseable(healthcare_spending2, mask_prices2)==expected3)) test_24() # Task 2.5 def compute_stringency_index(stringency_values): ''' Computes the daily stringency index for each country. Parameters ---------- stringency_values: np.ndarray 3D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the stringency values as a vector. To be specific, on each day, there are four different stringency values for 'school closing', 'workplace closing', 'stay at home requirements' and 'international travel controls', respectively. For instance, the (i, j, 0) entry represents the `school closing` stringency value for the ith country on the (j + 1)th day. Returns ------- Daily stringency index for each country as a 2D `ndarray` such that the (i, j) entry corresponds to the stringency index in the ith country on the (j + 1)th day. In this case, we shall assume that 'stay at home requirements' is the most restrictive regulation among the other regulations, 'international travel controls' is more restrictive than 'school closing' and 'workplace closing', and 'school closing' and 'workplace closing' are equally restrictive. Thus, to compute the stringency index, we shall weigh each stringency value by 1, 1, 3 and 2 for 'school closing', 'workplace closing', 'stay at home requirements' and 'international travel controls', respectively. Then, the index for the ith country on the (j + 1)th day is given by `stringency_values[i, j, 0] + stringency_values[i, j, 1] + 3 * stringency_values[i, j, 2] + 2 * stringency_values[i, j, 3]`. Note ---- Use matrix operations and broadcasting to complete this question. Please do not use iterative approaches like for-loops. ''' # TODO: add your solution here and remove `raise NotImplementedError` # print(stringency_values) return stringency_values @ np.array([1, 1, 3, 2]) # Test case for Task 2.5 def test_25(): stringency_values = np.ones((10, 20, 4)) stringency_values[:, 10:, :] *= 2 actual = compute_stringency_index(stringency_values) expected = np.ones((10, 20)) * (1 + 1 + 3 + 2) expected[:, 10:] *= 2 assert(np.all(actual == expected)) stringency_values2 = np.array([[[0, 0, 0, 0], [1, 0, 0, 0]], [[0, 0, 0, 0], [0, 1, 2, 0]]]) actual2 = compute_stringency_index(stringency_values2) expected2 = np.array([[0, 1], [0, 7]]) assert(np.all(actual2 == expected2)) test_25() # Task 2.6 def average_increase_in_cases(n_cases_increase, n_adj_entries_avg=7): ''' Averages the increase in cases for each day using data from the previous `n_adj_entries_avg` number of days and the next `n_adj_entries_avg` number of days. Parameters ---------- n_cases_increase: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the daily increase in the number of confirmed cases in that country, i.e. the ith row of `n_cases_increase` contains the data of the ith country, and the (i, j) entry of `n_cases_increase` is the daily increase in the number of confirmed cases on the (j + 1)th day in the ith country. n_adj_entries_avg: int Number of days from which data will be used to compute the average increase in cases. This should be a positive integer. Returns ------- Mean increase in cases for each day, using data from the previous `n_adj_entries_avg` number of days and the next `n_adj_entries_avg` number of days, as a 2D `ndarray` such that the (i, j) entry represents the average increase in daily cases on the (j + 1)th day in the ith country, rounded down to the smallest integer. The average increase in cases for a particular country on the (j + 1)th day is given by the mean of the daily increase in cases over the interval [-`n_adj_entries_avg` + j, `n_adj_entries_avg` + j]. (Note: this interval includes the endpoints). Note ---- Since this computation requires data from the previous `n_adj_entries_avg` number of days and the next `n_adj_entries_avg` number of days, it is not possible to compute the average for the first and last `n_adj_entries_avg` number of days. Therefore, set the average increase in cases for these days to `np.nan` for all countries. ''' sd_win = np.lib.stride_tricks.sliding_window_view(n_cases_increase, 2 * n_adj_entries_avg + 1, axis=1) avg = np.floor(np.mean(sd_win, axis=2)) res = np.pad(avg, ((0, 0), (n_adj_entries_avg, n_adj_entries_avg)), 'constant', constant_values=(np.nan, np.nan)) return res # Test case for Task 2.6 def test_26(): n_cases_increase = np.array([[0, 5, 10, 15, 20, 25, 30]]) actual = average_increase_in_cases(n_cases_increase, n_adj_entries_avg=2) expected = np.array([[np.nan, np.nan, 10, 15, 20, np.nan, np.nan]]) assert(np.array_equal(actual, expected, equal_nan=True)) # test_26() # Task 2.7 def is_peak(n_cases_increase_avg, n_adj_entries_peak=7): ''' Determines whether the (j + 1)th day was a day when the increase in cases peaked in the ith country. Parameters ---------- n_cases_increase_avg: np.ndarray 2D `ndarray` with each row representing the data of a country, and the columns of each row representing the time series data of the average daily increase in the number of confirmed cases in that country, i.e. the ith row of `n_cases_increase` contains the data of the ith country, and the (i, j) entry of `n_cases_increase` is the average daily increase in the number of confirmed cases on the (j + 1)th day in the ith country. In this case, the 'average' is computed using the output from `average_increase_in_cases`. n_adj_entries_peak: int Number of days that determines the size of the window in which peaks are to be detected. Returns ------- 2D `ndarray` with the (i, j) entry indicating whether there is a peak in the daily increase in cases on the (j + 1)th day in the ith country. Suppose `a` is the average daily increase in cases, with the (i, j) entry indicating the average increase in cases on the (j + 1)th day in the ith country. Moreover, let `n_adj_entries_peak` be denoted by `m`. In addition, an increase on the (j + 1)th day is deemed significant in the ith country if `a[i, j]` is greater than 10 percent of the mean of all average daily increases in the country. Now, to determine whether there is a peak on the (j + 1)th day in the ith country, check whether `a[i, j]` is maximum in {`a[i, j - m]`, `a[i, j - m + 1]`, ..., `a[i, j + m - 1]`, `a[i, j + m]`}. If it is and `a[i, j]` is significant, then there is a peak on the (j + 1)th day in the ith country; otherwise, there is no peak. Note ---- Let d = `n_adj_entries_avg` + `n_adj_entries_peak`, where `n_adj_entries_avg` is that used to compute `n_cases_increase_avg`. Observe that it is not possible to detect a peak in the first and last d days, i.e. these days should not be peaks. As described in `average_increase_in_cases`, to compute the average daily increase, we need data from the previous and the next `n_adj_entries_avg` number of days. Hence, we won't have an average for these days, precluding the computation of peaks during the first and last `n_adj_entries_avg` days. Moreover, similar to `average_increase_in_cases`, we need the data over the interval [-`n_adj_entries_peak` + j, `n_adj_entries_peak` + j] to determine whether the (j + 1)th day is a peak. Hint: to determine `n_adj_entries_avg` from `n_cases_increase_avg`, `np.count_nonzero` and `np.isnan` may be helpful. ''' # get the number of paddings to add (count nans and / 2) paddings = int(np.count_nonzero(np.isnan(n_cases_increase_avg[0])) / 2) nanless = n_cases_increase_avg[:, paddings: -paddings] # find peaks (get the sliding window) sd_win = np.lib.stride_tricks.sliding_window_view(nanless, 2 * n_adj_entries_peak + 1, axis=1) mids = sd_win[:, :, n_adj_entries_peak] left_vals = np.max(sd_win[:, :, :n_adj_entries_peak], axis=2) right_vals = np.max(sd_win[:, :, n_adj_entries_peak+1:], axis=2) peaks = (mids > left_vals) & (mids >= right_vals) means = np.nanmean(nanless, axis=1)[:, np.newaxis] * 0.1 significant = mids > means result = np.logical_and(peaks, significant) res = np.pad(result, ((0, 0), (paddings+n_adj_entries_peak, paddings+ n_adj_entries_peak)), 'constant', constant_values=(False, False)) return res def test_27(): n_cases_increase_avg = np.array([[np.nan, np.nan, 10, 10, 5, 20, 7, np.nan, np.nan], [np.nan, np.nan, 15, 5, 16, 17, 17, np.nan, np.nan]]) n_adj_entries_peak = 1 actual = is_peak(n_cases_increase_avg, n_adj_entries_peak=n_adj_entries_peak) expected = np.array([[False, False, False, False, False, True, False, False, False], [False, False, False, False, False, True, False, False, False]]) assert np.all(actual == expected) n_cases_increase_avg2 = np.array([[np.nan, np.nan, 10, 20, 20, 20, 20, np.nan, np.nan], [np.nan, np.nan, 20, 20, 20, 20, 10, np.nan, np.nan]]) n_adj_entries_peak2 = 1 actual2 = is_peak(n_cases_increase_avg2, n_adj_entries_peak=n_adj_entries_peak2) expected2 = np.array([[False, False, False, True, False, False, False, False, False], [False, False, False, False, False, False, False, False, False]]) assert np.all(actual2 == expected2) test_27() def visualise_increase(n_cases_increase, n_cases_increase_avg=None): ''' Visualises the increase in cases for each country that is represented in `n_cases_increase`. If `n_cases_increase_avg` is passed into the function as well, visualisation will also be done for the average increase in cases for each country. NOTE: If more than 5 countries are represented, only the plots for the first 5 countries will be shown. ''' days = np.arange(1, n_cases_increase.shape[1] + 1) plt.figure() for i in range(min(5, n_cases_increase.shape[0])): plt.plot(days, n_cases_increase[i, :], label='country {}'.format(i)) plt.legend() plt.title('Increase in Cases') if n_cases_increase_avg is None: plt.show() return plt.figure() for i in range(min(5, n_cases_increase_avg.shape[0])): plt.plot(days, n_cases_increase_avg[i, :], label='country {}'.format(i)) plt.legend() plt.title('Average Increase in Cases') plt.show() def visualise_peaks(n_cases_increase_avg, peaks): ''' Visualises peaks for each of the country that is represented in `n_cases_increase_avg` according to variable `peaks`. NOTE: If there are more than 5 countries, only the plots for the first 5 countries will be shown. ''' days = np.arange(1, n_cases_increase_avg.shape[1] + 1) plt.figure() for i in range(min(5, n_cases_increase_avg.shape[0])): plt.plot(days, n_cases_increase_avg[i, :], label='country {}'.format(i)) peak = (np.nonzero(peaks[i, :]))[0] peak_days = peak + 1 # since data starts from day 1, not 0 plt.scatter(peak_days, n_cases_increase_avg[i, peak]) plt.legend() plt.show() if __name__ == "__main__": df = get_data() n_cases_cumulative = get_n_cases_cumulative(df) n_deaths_cumulative = get_n_deaths_cumulative(df) healthcare_spending = get_healthcare_spending(df) mask_prices = get_mask_prices(healthcare_spending.shape[1]) stringency_values = get_stringency_values(df) n_cases_top_cumulative = get_n_cases_top_cumulative(df)