<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Jupyter Notebook and NumPy introduction
Jupyter notebook is often used by data scientists who work in Python. It is loosely based on Mathematica and combines code, text and visual output in one page.
Basic Jupyter Notebook commands
Some relevant short cuts
Step1:  Imports
In Python you need to import tools to be able to use them. In this workshop we will mainly use the numpy toolbox and you can import it like this
Step2:  Parts to be implemented
In cells like the following example you are expected to implement some code. The remainder of the tutorial won't work if you skip these.
Sometimes assertions are added as a check.
Step3:  Numpy arrays
We'll be often working with numpy arrays so here's a short introduction. 
np.array() create a new array.
Step4:  Notice how we used print(f"foo {bar}") to enter a variable bar into the print statement using curly brackets? This syntax is called 'f-strings' (notice the f before the first quote), extra documentation can be found here.
Step5:  Basic arithmetical operations on arrays of the same shape are done elementwise
Step6:  Data plotting
We use matplotlib.pyplot to make various types of plots
Step7:  A basic plot a list of values
Step8:  Plotting a list of X and Y values
Step9:  Using mathematical functions and plotting more than one line on a graph
Step10:  Data import and inspection (optional)
Pandas is a popular library for data wrangling, we'll use it to load and inspect a csv file that contains the historical web request and cpu usage of a web server
Step11:  The head command allows one to quickly inspect the first rows of the loaded data
Step12:  We can select the CPU column and plot the data
Step13:  Note that to show the plot, we need to import matplotlib.pyplot and execute the show() function.
Next we plot the request rates, leaving out the CPU column  as it has another unit
Step14:  Now to continue and start on modelling the data, we'll work with basic numpy arrays. By doing this we also drop the time-information as shown in the plots above.
We extract the column labels as the request_names for later reference
Step15:  We extract the request rates as a 2-dimensional numpy array
Step16:  and the cpu usage as a one-dimensional numpy array
<ASSISTANT_TASK:>
Python Code:
print('Hello world!')
print(list(range(5)))
Explanation: Jupyter Notebook and NumPy introduction
Jupyter notebook is often used by data scientists who work in Python. It is loosely based on Mathematica and combines code, text and visual output in one page.
Basic Jupyter Notebook commands
Some relevant short cuts:
* SHIFT + ENTER executes 1 block of code called a cell
* Tab-completion is omnipresent after the import of a package has been executed
* SHIFT + TAB gives you extra information on what parameters a function takes
* Repeating SHIFT + TAB multiple times gives you even more information
To get used to these short cuts try them out on the cell below.
End of explanation
import numpy as np
Explanation: Imports
In Python you need to import tools to be able to use them. In this workshop we will mainly use the numpy toolbox and you can import it like this:
End of explanation
# To proceed, implement the missing code, and remove the 'raise NotImplementedException()'
##### Implement this part of the code #####
raise NotImplementedError("Code not implemented, follow the instructions.")
# three = ?
assert three == 3
print('Good job!')
Explanation: Parts to be implemented
In cells like the following example you are expected to implement some code. The remainder of the tutorial won't work if you skip these.
Sometimes assertions are added as a check.
End of explanation
import numpy as np
# This is a two-dimensional numpy array:
arr = np.array([[1,2,3,4],[5,6,7,8]])
print(arr, '\n')
# The shape is a tuple describing the size of each dimension
print(f"shape={arr.shape}")
# Elements are selected by specifying two indices, counting from 0
print(f"arr[1][3] = {arr[1][3]}", '\n')
# This is a three-dimensional numpy array
arr3 = np.array([[[1, 2, 3, 4], [5, 6, 7, 8]], [[9, 10, 11, 12], [13, 14, 15, 16]]])
print(arr3, '\n')
print(f"shape={arr3.shape}")
# Elements in a three dimensional array are selected by specifying three indices, counting from 0
print(f"arr3[1][0][2] = {arr3[1][0][2]}")
Explanation: Numpy arrays
We'll be often working with numpy arrays so here's a short introduction. 
np.array() create a new array.
End of explanation
# The numpy reshape method allows one to change the shape of an array, while keeping the underlying data.
# One can leave one dimension unspecified by passing -1, it will be determined from the size of the data.
print("Original array:")
print(arr, '\n')
print("As 4x2 matrix")
print(np.reshape(arr, (4,2)), '\n')
print("As 8x1 matrix")
print(np.reshape(arr, (-1,1)), '\n')
print("As 2x2x2 array")
print(np.reshape(arr, (2,2,-1)))
# the numpy sum, mean min and max can be used to calculate aggregates across any axis
table = np.array([[10.9, 12.1, 15.2, 7.3], [3.9, 1.2, 34.6, 8.3], [1.9, 23.3, 1.2, 3.7]])
print(table)
# Calculating the maximum across the first axis (=0).
max0 = np.max(table, axis=0)
# Calculating the maximum across the second axis (=1).
max1 = np.max(table, axis=1)
# Calculating the overall maximum.
max_overall = np.max(table)
print(f"Maximum over the rows of the table = {max0}")
print(f"Maximum over the columns of the table = {max1}")
print(f"Overall maximum of the table = {max_overall}")
Explanation: Notice how we used print(f"foo {bar}") to enter a variable bar into the print statement using curly brackets? This syntax is called 'f-strings' (notice the f before the first quote), extra documentation can be found here.
End of explanation
x = np.array([1.,2.,3.])
y = np.array([4.,5.,6.])
print(x + y)
print(x - y)
print(x * y)
print(x / y)
Explanation: Basic arithmetical operations on arrays of the same shape are done elementwise:
End of explanation
import matplotlib.pyplot as plt
Explanation: Data plotting
We use matplotlib.pyplot to make various types of plots
End of explanation
plt.plot([7.3, 8.2, 1.2, 3.2, 9.1, 1.5])
plt.show()
Explanation: A basic plot a list of values
End of explanation
plt.plot([100.0, 110.0, 120.0, 130.0, 140.0, 150.0],[2.3, 8.1, 9.3, 9.7, 9.8, 20.0])
plt.show()
Explanation: Plotting a list of X and Y values
End of explanation
x = np.arange(0, 10, 0.1)
print(x)
# Most numpy function work on arrays as well by applying the function to each element in turn
y_cos = np.cos(x)
y_sin = np.sin(x)
plt.figure(figsize=(13, 6))
plt.plot(x, y_cos, x, y_sin)
plt.show()
Explanation: Using mathematical functions and plotting more than one line on a graph
End of explanation
import pandas as pd
data = pd.read_csv("data/request_rate_vs_CPU.csv")
print(f'The dataframe has {data.shape[0]} rows and {data.shape[1]} columns')
Explanation: Data import and inspection (optional)
Pandas is a popular library for data wrangling, we'll use it to load and inspect a csv file that contains the historical web request and cpu usage of a web server:
End of explanation
data.head()
Explanation: The head command allows one to quickly inspect the first rows of the loaded data:
End of explanation
data.plot(figsize=(13, 6), y="CPU")
plt.show()
Explanation: We can select the CPU column and plot the data:
End of explanation
data.drop(columns='CPU').plot(figsize=(13, 6))
plt.show()
Explanation: Note that to show the plot, we need to import matplotlib.pyplot and execute the show() function.
Next we plot the request rates, leaving out the CPU column  as it has another unit:
End of explanation
request_names = data.drop(columns='CPU').columns.values
request_names
Explanation: Now to continue and start on modelling the data, we'll work with basic numpy arrays. By doing this we also drop the time-information as shown in the plots above.
We extract the column labels as the request_names for later reference:
End of explanation
request_rates = data.drop(columns='CPU').values
print(request_rates.shape)
request_rates
Explanation: We extract the request rates as a 2-dimensional numpy array:
End of explanation
cpu = data['CPU'].values
cpu
Explanation: and the cpu usage as a one-dimensional numpy array
End of explanation
<END_TASK>