# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Solutions for the exercises in the notebook: Introduction to numpy

# # Exercise 1

# +
# a) Create array with units of seconds through the day, from 00:00 to 24:00, inclusive 
# b) Change the length of your array, to have either 1 second, 1 minute, or 1 hour intervals.
# (enter your code below)
# -

# a)
import numpy as np
np.linspace(0,86400,86401)
# or: np.arange(0,86401)

# b)
np.linspace(0,86400,24*60+1) # minutes
np.linspace(0,86400,24+1) # hours

# ---
#
# # Exercise 2

# Create a 2D NumPy array from the following list and assign it to the variable "a":

# +
# [[2, 3.2, 5.5, -6.4, -2.2, 2.4],
#  [1, 22, 4, 0.1, 5.3, -9],
#  [3, 1, 2.1, 21, 1.1, -2]]

# +
# Solution
a=np.array([[2, 3.2, 5.5, -6.4, -2.2, 2.4],
  [1, 22, 4, 0.1, 5.3, -9],
  [3, 1, 2.1, 21, 1.1, -2]])

print(a)
# -

# a) Can you guess what the following slices are equal to? Print them to check your understanding.

a[:, 3]
# This is the 4th column of a (recall that we start indexing with 0)

a[1:4, 0:4]
# rows 1 to 4 (second to last) and columns first to fourth

a[1:, 2]
# All raws starting from the second and the third column

# b) How would you extract: i) the last column; ii) the row before last?

# i)
a[:,-1] # This is the last column

# ii)
a[-2,:] # This is the row before last

# ---
#
# # Exercise 3

# + [markdown] nbpresent={"id": "5e485850-9bbe-419f-82bb-d7fcd39be095"}
# Consider a 4 x 5 2D array of negative integers:

# + nbpresent={"id": "e4b78e95-ad9a-4a6d-a54b-68d7d4a72eab"}
a = np.arange(-100, 0, 5).reshape(4, 5)
a

# + [markdown] nbpresent={"id": "ccf808ae-2412-4e53-bb29-d3101eccc925"}
# Suppose you want to return an array `result`, which has the squared value when an element in array `a` is greater than `-90` and less than `-40`, and is 1 otherwise.

# + [markdown] nbpresent={"id": "29981bec-1784-4ca7-b609-749858503e45"} slideshow={"slide_type": "subslide"}
# Using a `for` loop, the result could look like this:

# + nbpresent={"id": "a508de6d-2d13-4938-a145-d1159600a619"}
result = np.zeros(a.shape, dtype=a.dtype)    # pre-allocate a result array

for i in range(a.shape[0]):                  # loop over rows
    for j in range(a.shape[1]):              # loop over columns
        if a[i, j] > -90 and a[i, j] < -40:  # only square the number if within the chosen limits
            result[i, j] = a[i, j]**2
        else:                                # set to 1 otherwise
            result[i, j] = 1
            
result

# + [markdown] nbpresent={"id": "29981bec-1784-4ca7-b609-749858503e45"} slideshow={"slide_type": "subslide"}
# **Can you write a vectorised solution?**
#
# Hint: use np.logical_and() and/or np.logical_not() to create a condition
#

# +
# Example solution 1: 

result = np.ones(a.shape,dtype=a.dtype)              # set all values to 1 at start
square_values = np.logical_and(a>-90,a<-40)          # create a boolean array -> true within set limits
result[square_values] = np.square(a[square_values])  # only square values where square_values==true.
print(result)

# +
# Example solution 2 - A one-liner using `np.where`:

result = np.where(np.logical_and(a>-90,a<-40), a**2, 1)
print(result)
# -

# help(np.where)


# ---
#
# # Exercise 4

# + [markdown] nbpresent={"id": "8b2e92c7-13c0-4a2c-9efa-b034914c63d2"}
# 1. Create a "data" array of evenly spaced numbers, in the interval (-10, 20) spaced by 0.5
# 2. Calculate the (natural) logarithm of the data
# 3. Create a condition i.e. a True/False (boolean) array, that you can use to mask these results
#     - The resulting array should be masked when either of the following conditions apply
#         - larger or equal than 10
#         - larger than -1 and smaller than 1 
#         - data is not a real number
# 4. Mask the array depending on these conditions
#

# + nbpresent={"id": "ef21490b-e603-4991-a0df-0ebdccef705b"} slideshow={"slide_type": "subslide"}
# Your code:
# Hint: use `np.linspace` or `np.arange` functions

# 1. 
data = np.arange(-10,20.1,0.5)
print(data)
# -

# 2.
logdata = np.log(data)
print(logdata)

# + nbpresent={"id": "24ca4668-8118-4652-bc6a-3fc80dd52b2c"}
# 3. Hint: use np.isfinite
condition = np.logical_or(~np.isfinite(logdata), np.logical_or(logdata>=10, np.logical_and(logdata>-1,logdata<1)))
print(condition)

#Another possible condition giving the same result would be:
condition = np.logical_or(np.logical_not(np.isfinite(arr)), np.logical_or(abs(arr)<1,arr>=10))
print(condition)


# + nbpresent={"id": "8e131b42-9337-499d-9192-e8250ca8ae6c"}
# 4. Hint: use np.ma.masked_where(condition,arr)

masked_arr= np.ma.masked_where(condition, logdata)
print(masked_arr)
# -

# ---
#
# # Exercise 5

# Generate a 2d array with 5x5. The first value is 0 and it grows left to right and top to bottom in increments on 0.1.

e4 = np.arange(0.,2.5,.1)
e4

#Another possibility
e4=np.linspace(0.,2.4,25)
e4

e4.reshape([5,5])

StarcoderdataJupyterScriptsDedupFiltered