{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction to Python and Numpy\n", "\n", "As part of this course, we will use the Python programming language in combination with the Jupyter environment and various libraries (Numpy, Matplotlib, OpenCV, Librosa,...), which will make it easier for you to work with images, videos and audio files.\n", "\n", "For each exercise you will recieve a Jupyter notebook template, where you will write down your solutions in the places provided for that purpose. For solving the exercises you are encouraged to use our provided Jupyter server (lab.vicos.si), where all necessary libraries are already preinstalled. However, you are free to use the alternatives such as: our docker image, your local computer or the Google Colab service.\n", "\n", "Before we begin with our Python+Numpy crash course, please make sure you have the following libraries installed:\n", "* NumPy (pip install numpy)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Quick introduction to Python\n", "\n", "### Basic data types\n", "\n", "Like most of the programming languages, Python too has numerous basic data types such as integers, floats, booleans, ... In the following few excercises we will quickly overview these datatypes with some practical examples.\n", "\n", "#### Numbers (integers, floats):" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "3\n", "4\n", "2\n", "6\n", "9\n", "4\n", "8\n", "\n", "2.5 3.5 5.0 6.25\n" ] } ], "source": [ "x = 3 # Initializes the variable x with a value 3. Python automatically figures out, that the type of variable x is integer\n", "# If we want to check the type of a variable, we can do so by executing type()\n", "print(type(x)) # Prints the type of variable x --- \"\"\n", "\n", "print(x) # Prints the value of variable x --- \"3\"\n", "print(x + 1) # Addition; Prints \"4\"\n", "print(x - 1) # Subtraction; Prints \"2\"\n", "print(x * 2) # Multiplication; Prints \"6\"\n", "print(x ** 2) # Exponentiation; Prints \"9\"\n", "\n", "x += 1 # Increments x by 1\n", "# Note that Python does not have unary increment (x++) or decrement (x--) operators\n", "print(x) # Prints new value of variable x --- \"4\"\n", "x *= 2 # Multiply current value of the variable x with 2 (4*2)\n", "print(x) # Print new value of the variable x --- \"8\"\n", "\n", "y = 2.5 # Initializes the variable y with a value 2.5. Python automatically figures out, that the type of variable y is float\n", "print(type(y)) # Prints the type of the variable y --- \"\"\n", "print(y, y + 1, y * 2, y ** 2) # Prints \"2.5 3.5 5.0 6.25\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Booleans\n", "\n", "Python supports all usual boolean operations. The only difference is, that it uses English words (```and```, ```or```,...) instead of boolean symbols (```&&```, ```||```,...)\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "False\n", "True\n", "False\n", "True\n" ] } ], "source": [ "t = True # Initialize variable t with value True. Python automatically figures out, that the type is boolean\n", "f = False # Initialize variable f with value False. Python automatically figures out, that the type is boolean\n", "\n", "print(type(t)) # Prints \"\"\n", "\n", "# Executing boolean operation AND\n", "print(t and f) # True AND False = False; Prints \"False\"\n", "\n", "# Executing boolean operation OR\n", "print(t or f) # True OR False = True; Prints \"True\"\n", "\n", "# Executing boolean operation NOT\n", "print(not t) # NOT True = False; Prints \"False\"\n", "\n", "# Executing boolean operation XOR\n", "print(t != f) # True XOR False = True; Prints \"True\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Strings" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "hello world\n", "hello world 12\n", "Hello\n", "HELLO\n", " hello\n", " hello \n", "heavy\n", "world\n" ] } ], "source": [ "# Initializing variables of type string\n", "hello = 'hello' # Strings can be written inside a single quotes\n", "world = \"world\" # or double quotes\n", "\n", "# We can obtain the length (the number of characters) of a string with function len()\n", "print(len(hello)) # Prints the length of the string --- \"5\"\n", "\n", "# Multiple strings are joined with concatenation\n", "hw = hello + ' ' + world # String concatenation\n", "print(hw) # Prints \"hello world\"\n", "\n", "# Strings can also be joined using the sprintf formatting\n", "hw12 = '%s %s %d' % (hello, world, 12) # the sprintf formatting\n", "print(hw12) # Prints \"hello world 12\"\n", "\n", "# Python also supports multiple other operations on strings\n", "print(hello.capitalize()) # Capitalizes the first letter of the string; Prints \"Hello\"\n", "print(hello.upper()) # Converts letters in a string to uppercase; Prints \"HELLO\"\n", "print(hello.rjust(7)) # Right-justify a string and pad it with spaces; Prints \" hello\"\n", "print(hello.center(7)) # Center a string and pad it with spaces left and right; Prints \" hello \"\n", "print(hello.replace('llo', 'avy')) # Replaces all occurances of a first substring in a string with a second substring; Prints \"heavy\"\n", "print(' world '.strip()) # Removes leading and trailing whitespaces; Prints \"world\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Containers\n", "\n", "#### List\n", "\n", "A list in Python is similar to the array with two main differences:\n", "1. Its length is not defined in advance (it can be resized)\n", "2. It can contain elements of different types\n", "\n", "For more informations about lists read the official documentation." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 1, 2]\n", "2\n", "2\n", "3\n", "[3, 1, 'foo']\n", "[3, 1, 'foo', 'bar']\n", "bar\n", "[3, 1, 'foo']\n" ] } ], "source": [ "xs = [3, 1, 2] # Create a list xs with three elements of type integer\n", "\n", "print(xs) # Prints the whole list --- \"[3, 1, 2]\"\n", "print(xs[2]) # Prints the third element in the list xs --- \"2\". Positive indices count from the start of the list and begin with 0\n", "print(xs[-1]) # Prints the last element of the list xs --- \"2\". Negative indices count from the end of the list and begin with -1\n", "print(len(xs)) # Prints the length of the list (the number of elements) --- \"3\"\n", "\n", "xs[2] = 'foo' # Overwrites the third element with a string 'foo'. Remember, lists can contain elements of different types\n", "print(xs) # Prints the whole list --- \"[3, 1, 'foo']\"\n", "\n", "xs.append('bar') # Appends a new element to the end of the list\n", "print(xs) # Prints \"[3, 1, 'foo', 'bar']\"\n", "x = xs.pop() # Removes the last element from the list and saves it to the variable x\n", "print(x) # Prints \"bar\"\n", "print(xs) # Prints \"[3, 1, 'foo']\"" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4]\n", "[2, 3]\n", "[2, 3, 4]\n", "[0, 1]\n", "[0, 1, 2, 3, 4]\n", "[0, 1, 2, 3]\n", "[0, 1, 8, 9, 4]\n" ] } ], "source": [ "nums = list(range(5)) # Range is a built-in function that creates a list of integers\n", "print(nums) # Prints \"[0, 1, 2, 3, 4]\"\n", "print(nums[2:4]) # Get a slice from index 2 to 4 (exclusive); prints \"[2, 3]\"\n", "print(nums[2:]) # Get a slice from index 2 to the end; prints \"[2, 3, 4]\"\n", "print(nums[:2]) # Get a slice from the start to index 2 (exclusive); prints \"[0, 1]\"\n", "print(nums[:]) # Get a slice of the whole list; prints \"[0, 1, 2, 3, 4]\"\n", "print(nums[:-1]) # Slice indices can be negative; prints \"[0, 1, 2, 3]\"\n", "nums[2:4] = [8, 9] # Assign a new sublist to a slice\n", "print(nums) # Prints \"[0, 1, 8, 9, 4]\"" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cat\n", "dog\n", "monkey\n", "#1: cat\n", "#2: dog\n", "#3: monkey\n" ] } ], "source": [ "# Creates a new list with three elements - 'cat', 'dog', 'monkey'\n", "animals = ['cat', 'dog', 'monkey']\n", "\n", "# We can loop over elements of the list using the FOR loop\n", "for animal in animals:\n", " print(animal)\n", "# Prints \"cat\", \"dog\", \"monkey\"; each in its own line\n", "\n", "\n", "# If we want to access the index of each element within the body of a loop, then we can use the built-in enumerate() function\n", "for idx, animal in enumerate(animals):\n", " print('#%d: %s' % (idx + 1, animal))\n", "# Prints \"#1: cat\", \"#2: dog\", \"#3: monkey\"; each in its own line" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 4, 9, 16]\n", "[0, 4, 16]\n" ] } ], "source": [ "nums = [0, 1, 2, 3, 4] # Create a new list of integers\n", "squares = [x ** 2 for x in nums] # Generate a new list based on values of the existing list nums; Each value in squares will be a squared value of a corresponding value in nums\n", "print(squares) # Prints \"[0, 1, 4, 9, 16]\"\n", "\n", "# When generating lists we can also use boolean operations:\n", "even_squares = [x ** 2 for x in nums if x % 2 == 0] # Take only even numbers from nums and add their squared values to a new list even_squares\n", "print(even_squares) # Prints \"[0, 4, 16]\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Dictionaries\n", "\n", "Dictionaries store pairs (key, value). Below, we will briefly look at some examples involving dictionaries. For more informations regarding dictionaries, please take a look at the offical documentation." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cute\n", "True\n", "N/A\n", "wet\n", "N/A\n" ] } ], "source": [ "# Create a new dictionary. The key \"cat\" has corresponding value \"cute\" and the key \"dog\" has corresponding value \"furry\"\n", "d = {'cat': 'cute', 'dog': 'furry'}\n", "\n", "# d['cat'] gets the value that corresponds to the key \"cat\"\n", "print(d['cat']) # Prints \"cute\"\n", "\n", "# To check whether the key \"cat\" exists in the dictionary d, use: \"cat\" in d\n", "print('cat' in d) # Prints \"True\"\n", "\n", "# To add a new key and value pair to the dictionary d, simply use:\n", "d['fish'] = 'wet'\n", "\n", "# If we try to access a non-existing key, we get an error\n", "# print(d['monkey']) # KeyError: 'monkey' not a key of d\n", "\n", "# We can \"by-pass\" the error by using the get() method\n", "print(d.get('monkey', 'N/A')) # Prints \"N/A\", because the key \"monkey\" does not exists in the dictionary d\n", "print(d.get('fish', 'N/A')) # Prints \"wet\", because the key \"fish\" exists in the dictionary d\n", "\n", "# To delete a (key, value) pair from the dictionary we use command: del\n", "del d['fish'] # Deletes the key \"fish\" and its corresponding value from the dictionary d\n", "print(d.get('fish', 'N/A')) # Prints \"N/A\", because the key \"fish\" does not exists anymore in the dictionary d" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A person has 2 legs\n", "A cat has 4 legs\n", "A spider has 8 legs\n", "{0: 0, 2: 4, 4: 16}\n" ] } ], "source": [ "# We can use a simple FOR loop to iterate through the keys in a dictionary:\n", "d = {'person': 2, 'cat': 4, 'spider': 8}\n", "for animal, legs in d.items(): # the current key gets saved to the variable animal, while its corresponding value gets saved to the variable legs\n", " print('A %s has %d legs' % (animal, legs))\n", "# Prints \"A person has 2 legs\", \"A cat has 4 legs\" and \"A spider has 8 legs\"; each in its own line\n", "\n", "# We can also use boolean operations in dictionary comprehensions:\n", "nums = [0, 1, 2, 3, 4]\n", "even_num_to_square = {x: x ** 2 for x in nums if x % 2 == 0}\n", "print(even_num_to_square) # Izpiše \"{0: 0, 2: 4, 4: 16}\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Sets\n", "\n", "A set is an unordered collection of distinct elements. You can read more about sets in the official documentation." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n", "3\n", "3\n", "2\n" ] } ], "source": [ "animals = {'cat', 'dog'}\n", "\n", "# Checking if an element is in a set\n", "print('cat' in animals) # Prints \"True\"\n", "print('fish' in animals) # Prints \"False\"\n", "\n", "animals.add('fish') # Adding a new (non-existing) element to a set\n", "\n", "# To get the number of elements in a set use function len()\n", "print(len(animals)) # Prints \"3\"\n", "animals.add('cat') # Adding a new, existing, element to a set; Nothing will happen\n", "print(len(animals)) # Prints \"3\"\n", "\n", "# To remove an elements from a set use function remove()\n", "animals.remove('cat') # Removes element \"cat\" from the set animals\n", "print(len(animals)) # Prints \"2\"" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#1: dog\n", "#2: fish\n", "#3: cat\n" ] } ], "source": [ "# We can use a simple FOR loop to iterate through the elements in a set:\n", "animals = {'cat', 'dog', 'fish'}\n", "for idx, animal in enumerate(animals):\n", " print('#%d: %s' % (idx + 1, animal))\n", "# Prints \"#1: fish\", \"#2: dog\", \"#3: cat\"; each in its own line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Tuples\n", "\n", "A tuple is an (immutable) ordered list of values. A tuple is in many ways similar to a list; one of the most important differences is that tuples can be used as keys in dictionaries and as elements of sets, while lists cannot. To learn more about tuples, please refer to the official documentation" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "5\n", "5\n", "1\n" ] } ], "source": [ "t = (5, 6) # Based on notation, Python automatically figures out, that the variable t is tuple\n", "\n", "print(type(t)) # Prints \"\"\n", "\n", "# We can access elements in a tuple the same way as we would for lists\n", "print(t[0]) # Prints \"5\"\n", "\n", "# Generating a dictionary with tuples as keys:\n", "d = {(x, x + 1): x for x in range(10)}\n", "\n", "# To access values in the dictionary d, we must now use tuples as keys\n", "print(d[t]) # Prints \"5\"\n", "print(d[(1, 2)]) # Prints \"1\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Functions\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions are defined with the word ```def```. To learn more about the functions, please refer to the official documentation." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Bob\n", "HELLO, FRED!\n" ] } ], "source": [ "# Define function hello, that takes two input arguments. The first one (name) is required, while the second one (loud) is optional and it will be used the default value in case if it is not specified.\n", "def hello(name, loud=False):\n", " if loud:\n", " print('HELLO, %s!' % name.upper())\n", " else:\n", " print('Hello, %s' % name)\n", "\n", "hello('Bob') # We input only one argument. The value of loud is False. Prints \"Hello, Bob\"\n", "hello('Fred', loud=True) # We input both arguments. Prints \"HELLO, FRED!\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Classes\n", "\n", "Classes are defined with the word ```class```. They typically have a constructor (function ```__init__()```). Read more about classes in the official documentation." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Fred\n", "HELLO, FRED!\n" ] } ], "source": [ "class Greeter(object):\n", "\n", " # Constructor\n", " def __init__(self, name):\n", " self.name = name # Create an instance variable\n", "\n", " # Instance method\n", " def greet(self, loud=False):\n", " if loud:\n", " print('HELLO, %s!' % self.name.upper())\n", " else:\n", " print('Hello, %s' % self.name)\n", "\n", "g = Greeter('Fred') # Construct an instance of the Greeter class\n", "g.greet() # Call an instance method; prints \"Hello, Fred\"\n", "g.greet(loud=True) # Call an instance method; prints \"HELLO, FRED!\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Quick introduction to NumPy\n", "\n", "NumPy is the most popular Python library for solving mathematical operations. Its main adventage is support for fast computation of matrix operations on multidimensionals arrays. If you already have experiences with Matlab, then using the NumPy library will be straight-forward.\n", "\n", "For more information regarding NumPy, read its official documentation.\n", "\n", "### Arrays\n", "\n", "A numpy array is a grid of values, all of the same type, and is indexed by a tuple of nonnegative integers. The number of dimensions is the rank of the array; the shape of an array is a tuple of integers giving the size of the array along each dimension." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "(3,)\n", "1 2 3\n", "[5 2 3]\n", "(2, 3)\n", "1 2 4\n", "[[0. 0.]\n", " [0. 0.]]\n", "[[1. 1.]]\n", "[[7 7]\n", " [7 7]]\n", "[[1. 0.]\n", " [0. 1.]]\n", "[[0.33447752 0.9920027 ]\n", " [0.51774148 0.4148667 ]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "a = np.array([1, 2, 3]) # Creates a rank 1 array with the shape of 3\n", "print(type(a)) # Prints \"\"\n", "\n", "print(a.shape) # Prints \"(3,)\"; This means, that the array is a rank 1 array with 3 elements in its first dimension.\n", "\n", "# We access the elements in the array the same way as in lists\n", "print(a[0], a[1], a[2]) # Prints \"1 2 3\"\n", "a[0] = 5 # Changes the value of the first element in the first dimension of the array a\n", "print(a) # Prints \"[5, 2, 3]\"\n", "\n", "b = np.array([[1,2,3],[4,5,6]]) # Creates a rank 2 array\n", "print(b.shape) # Prints \"(2, 3)\"; This means, that the array is a rank 2 array with 2 elements in the first dimension and 3 elements in the second dimension.\n", "print(b[0, 0], b[0, 1], b[1, 0]) # Prints \"1 2 4\"\n", "\n", "\n", "# Arrays can be also initialized in various other ways:\n", "a = np.zeros((2,2)) # Initialize a rank 2 array of zeros\n", "print(a) # Prints \"[[ 0. 0.]\n", " # [ 0. 0.]]\"\n", "\n", "b = np.ones((1,2)) # Initialize a rank 2 array of ones\n", "print(b) # Prints \"[[ 1. 1.]]\"\n", "\n", "c = np.full((2,2), 7) # Initialize a rank 2 array filled with the specified constant value (7)\n", "print(c) # Prints \"[[ 7. 7.]\n", " # [ 7. 7.]]\"\n", "\n", "d = np.eye(2) # Initialize a rank 2 array that is an identity matrix\n", "print(d) # Prints \"[[ 1. 0.]\n", " # [ 0. 1.]]\"\n", "\n", "e = np.random.random((2,2)) # Initialize a rank 2 array filled with random values (between 0 and 1)\n", "print(e) # It prints something like: \"[[ 0.91940167 0.08143941]\n", " # [ 0.68744134 0.87236687]]\"" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 5 3]\n", "[1 5 3]\n" ] } ], "source": [ "b = np.array([[1,2,3],[4,5,6]])\n", "\n", "# Primer indeksiranja večih elementov:\n", "# Prvi seznam nam pove indekse vrstic, drugi seznam nam pa pove indekse stolpcev\n", "print(b[[0, 1, 0], [0, 1, 2]]) # Prints \"[1 5 3]\"\n", "\n", "# Zgornji način indeksiranja lahko prepišemo v malo daljšo, vendar bolj pregledno obliko:\n", "print(np.array([b[0, 0], b[1, 1], b[0, 2]])) # Prints \"[1 5 3]\"" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1 2 3]\n", " [ 4 5 6]\n", " [ 7 8 9]\n", " [10 11 12]]\n", "[ 1 6 7 11]\n", "[[11 2 3]\n", " [ 4 5 16]\n", " [17 8 9]\n", " [10 21 12]]\n" ] } ], "source": [ "# Create a new array from which we will select elements\n", "a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n", "\n", "print(a) # Prints \"array([[ 1, 2, 3],\n", " # [ 4, 5, 6],\n", " # [ 7, 8, 9],\n", " # [10, 11, 12]])\"\n", "\n", "# Create an array of indices\n", "b = np.array([0, 2, 0, 1])\n", "\n", "# Select one element from each row of a using the indices in b\n", "print(a[np.arange(4), b]) # Prints \"[ 1 6 7 11]\"\n", "\n", "# Using the above example of indexing we can also update the values of a\n", "a[np.arange(4), b] += 10\n", "\n", "print(a) # Prints \"array([[11, 2, 3],\n", " # [ 4, 5, 16],\n", " # [17, 8, 9],\n", " # [10, 21, 12]])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ True False False]\n", " [False False True]\n", " [ True True True]\n", " [ True True True]]\n", "[11 16 17 8 9 10 21 12]\n", "[11 16 17 8 9 10 21 12]\n" ] } ], "source": [ "# We can also pick up arbitrary elements from the array using \"boolean masks\":\n", "\n", "bool_idx = (a > 5) # Create a boolean array with the same dimensionality as array a.\n", " # All elements, which value is larger than 5 get value True, otherwise False\n", " # Elements of the array bool_idx tell us which elements from the corresponding position in the array a are larger than 5\n", "\n", "print(bool_idx) # Prints \"[[ True False False]\n", " # [False False True]\n", " # [ True True True]\n", " # [ True True True]]\"\n", "\n", "# We can use the boolean array bool_idx to pick up elements from the array a which correspond to values True\n", "print(a[bool_idx]) # Prints \"[11 16 17 8 9 10 21 12]\"\n", "\n", "# We can also write the above lines in a more compact way: a[a > 5]\n", "print(a[a > 5]) # Prints \"[11 16 17 8 9 10 21 12]\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Datatypes\n", "\n", "It is neccessary that elements of an array are of the same type. Although Numpy provides a wide range of datatypes, we will mainly focus on the following few: int32, float64, boolean and uint8." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "1\n", "float64\n", "uint8\n", "[ 1 0 44 125 144 251 0]\n" ] } ], "source": [ "# When creating the array, Python will automatically unify datatypes of elements\n", "a = np.array([1, 'bla']) # All elements will be string\n", "print(type(a[0])) # We can check this by executing type(a[0]); It prints \n", "print(a[0]) # Prints \"1\"\n", "\n", "a = np.array([1, 0.1]) # All elements will be float64\n", "print(a.dtype) # To check the datatype of the array, execute a.dtype; It prints out \"float64\"\n", "\n", "\n", "# We can also manually specify the datatype of the array:\n", "a = np.array([1, 0, 300, 125, 400, -5, 256], dtype=np.uint8) # Elements will be uint8 (values from interval [0-255])\n", "print(a.dtype) # Prints \"uint8\"\n", "print(a) # Prints \"[ 1 0 44 125 144 251 0]\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Array math\n", "\n", "Mathematical operations are executed element-wise on the arrays. For the execution of basic mathematical operations we can either use numpy functions (```add()```, ```˙subtract()```,...) or standard symbols (```+```, ```-```,...)." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 6. 8.]\n", " [10. 12.]]\n", "[[ 6. 8.]\n", " [10. 12.]]\n", "[[-4. -4.]\n", " [-4. -4.]]\n", "[[-4. -4.]\n", " [-4. -4.]]\n", "[[ 5. 12.]\n", " [21. 32.]]\n", "[[ 5. 12.]\n", " [21. 32.]]\n", "[[ 6. 12.]\n", " [ 8. 14.]]\n", "[[6. 7.]\n", " [8. 9.]]\n", "[[19. 22.]\n", " [43. 50.]]\n", "[[19. 22.]\n", " [43. 50.]]\n", "[[0.2 0.33333333]\n", " [0.42857143 0.5 ]]\n", "[[0.2 0.33333333]\n", " [0.42857143 0.5 ]]\n", "[[1. 1.41421356]\n", " [1.73205081 2. ]]\n" ] } ], "source": [ "x = np.array([[1, 2], [3, 4]], dtype=np.float64)\n", "y = np.array([[5, 6], [7, 8]], dtype=np.float64)\n", "z = np.array([5, 10], dtype=np.float64)\n", "\n", "# Element-wise addition\n", "print(x + y)\n", "print(np.add(x, y))\n", "# Both return the same result:\n", "# [[ 6.0 8.0]\n", "# [10.0 12.0]]\n", "\n", "# Element-wise subtraction\n", "print(x - y)\n", "print(np.subtract(x, y))\n", "# Both return the same result:\n", "# [[-4.0 -4.0]\n", "# [-4.0 -4.0]]\n", "\n", "# Element-wise multiplication\n", "print(x * y)\n", "print(np.multiply(x, y))\n", "# Both return the same result:\n", "# [[ 5.0 12.0]\n", "# [21.0 32.0]]\n", "\n", "# When performing addition/subtraction/multiplication at least one of the following conditions has to be met:\n", "# - we are doing so with two arrays of the same shape\n", "# - we are doing so with an array and a vector, which share the same shape of the rows/columns\n", "# - we are doing so with an array and a scalar (constant)\n", "print(x + z) # Add the vector z to all rows of the array x\n", " # Prints [[ 6.0 12.0]\n", " # [ 8.0 14.0]]\n", "print(x + 5) # Add 5 to all elements of the array x\n", " # Prints [[6 7]\n", " # [8 9]]\n", "\n", "# For multiplication of two matrices we can use functions matmul() or dot()\n", "print(np.matmul(x, y))\n", "print(np.dot(x, y))\n", "# Both return the same result:\n", "# [[19.0 22.0]\n", "# [43.0 50.0]]\n", "#\n", "# The two main differences between matmul() and dot() are:\n", "# 1) matmul() does not support multiplication with scalar. For this, we must either use * or dot()\n", "# 2) when using matmul() the stacks of matrices are broadcast together as if the matrices were elements.\n", "\n", "# Element-wise division\n", "print(x / y)\n", "print(np.divide(x, y))\n", "# Both return the same result:\n", "# [[ 0.2 0.33333333]\n", "# [ 0.42857143 0.5 ]]\n", "\n", "# Element-wise square-root\n", "print(np.sqrt(x))\n", "# [[ 1. 1.41421356]\n", "# [ 1.73205081 2. ]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Numpy provides a wide range of usefull functions for performing various calculations on arrays (e.g. ```sum()```, ```mean()```,...)\n", "\n", "The whole list of these functions is available in documentation. Below, we will get familiar with some of the most common ones." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10.0\n", "[4. 6.]\n", "[3. 7.]\n", "2.5\n", "[2. 3.]\n", "[1.5 3.5]\n", "[[ 7. 15.]\n", " [22. 29.]]\n", "[[1. 3.]\n", " [2. 4.]]\n" ] } ], "source": [ "x = np.array([[1, 2], [3, 4]], dtype=np.float64)\n", "\n", "print(np.sum(x)) # Computes the summation of all elements in the array x; Prints \"10\"\n", "print(np.sum(x, axis=0)) # Computes the summation of all elements in each column of the array x; Prints \"[4 6]\"\n", "print(np.sum(x, axis=1)) # Computes the summation of all elements in each row of the array x; Prints \"[3 7]\"\n", "\n", "print(np.mean(x)) # Computes the average value of the array x; Prints \"2.5\"\n", "print(np.mean(x, axis=0)) # Computes the average value of each column in the array x; Prints \"[2 3]\"\n", "print(np.mean(x, axis=1)) # Computes the average value of each row in the array x; Prints \"[1.5 3.5]\"\n", "\n", "print(np.round(x * 7.3)) # Round the values to the nearest whole number\n", " # Prints [[ 7. 15.]\n", " # [22. 29.]]\n", " \n", "print(x.T) # Prints the transposed matrix x; [[1 3]\n", " # [2 4]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Most of the functions require input arrays to be of the same dimensionality and shape. When two arrays are of different shape, we can use the broadcasting technique to asssign them a uniform shape." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 1 1]\n", " [1 1 1]\n", " [1 1 1]]\n", "(3, 3)\n", "(3, 3)\n", "(1, 9)\n", "[[1 2 3 4 5 6 7 8 9]]\n", "(4, 3)\n", "[[0 1 2]\n", " [0 1 2]\n", " [0 1 2]\n", " [0 1 2]]\n", "(2, 6)\n", "[[0 1 2 0 1 2]\n", " [0 1 2 0 1 2]]\n", "(1, 6)\n", "[[0 1 2 0 1 2]]\n" ] } ], "source": [ "a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "\n", "# Creates an array b, filled with ones, that has the same shape as the array a\n", "b = np.ones_like(a)\n", "print(b) # Izpiše [[1, 1, 1]\n", " # [1, 1, 1]\n", " # [1, 1, 1]]\n", "print(a.shape) # Izpiše (3, 3)\n", "print(b.shape) # Izpiše (3, 3)\n", "\n", "# Creates an array, filled with zeros, that has the same shape as the array a\n", "c = np.zeros_like(a)\n", "# Alternatively we can use the empty_like() function, which produces the same result\n", "d = np.empty_like(a)\n", "\n", "# Using the reshape() function we can re-shape a certain array, however, the number of elements must not change\n", "a1 = np.reshape(a, (1, 9))\n", "print(a1.shape) # Prints (1, 9)\n", "print(a1) # Prints [[1 2 3 4 5 6 7 8 9]]\n", "\n", "\n", "a = np.array([0, 1, 2])\n", "# To repeat a row/column we can use function tile():\n", "a1 = np.tile(a, (4, 1)) # We duplicate vector a 4 times vertically and once horizontally. The result is an array of shape 4x3\n", "print(a1.shape) # Prints (4, 3)\n", "print(a1) # Prints [[0 1 2]\n", " # [0 1 2]\n", " # [0 1 2]\n", " # [0 1 2]]\n", "# We can further reshape the obtained array by using the reshape() function\n", "a1_2 = np.reshape(a1, (2, 6))\n", "print(a1_2.shape) # Prints (2, 6)\n", "print(a1_2) # Prints [[0 1 2 0 1 2]\n", " # [0 1 2 0 1 2]]\n", " \n", "a2 = np.tile(a, (1, 2)) # We repeat the vector a twice horizontally and once vertically. The result is an array of shape 1x6\n", "print(a2.shape) # Prints (1, 6)\n", "print(a2) # Prints [[0 1 2 0 1 2]]\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }