Vectors are a useful way of representing data in python. The better way to create vectors is by using the popular NumPy library. It also includes all the vector operations like addition, subtractions, dot product, etc. However, we will be using inbuilt methods to create vectors in this article. Python has no dedicated module or a method for creating vectors, so we will be using the type alias feature to accomplish it. This also means we will have to write all the functions for addition, subtraction, dot product, finding magnitude, and distance (between two vectors) ourselves. Using this method will be slow from a computational standpoint. This is only to understand the concept level thinking that goes into creating vectors.
A vector is a quantity that has a tail (starting point), a head (ending point), a direction, and magnitude. A direction and magnitude are enough to locate their path but having a tail and head can help us mark them at the exact location. One can perform operations like vector addition, subtraction, dot product, etc to arrive at necessary results. The below image is a simple illustration of a vector.
The above vector is in a 2D plane. We can however represent vectors in any number of dimensions, except 1D.
One might be thinking what is the use of representing our data in vector format. The use is simple, with vector we can conduct vector operations. We can also multiply them with numbers (scalars). For example, if a person is defined by his height, weight, and age then we can represent him with a 3D vector
[height, weight, age].
This vector will be standard for representing any person. All the persons will fit inside the vector space. We will be utilizing lists to write vectors in python. We will be defining our own functions to conduct vector operations. Before going forward, however, we need to learn two features of python which we will be using in this tutorial. They are type alias and assert keyword.
Python is a dynamically typed programming language. This means we don’t need to specify the type of our variables, arguments, etc. However, we can (since python 3.5) provide type but only as a hint. It will never be enforced by python however we can use third-party checkers like mypy to check if our code is correct. This is useful if we want to be careful about the types we use in our code. Here is a simple example.
def greeting(name: str) -> str: return 'Hello ' + name
In the above code, we are hinting that the argument of the function
greeting should be a string. However, it’s not enforced by python. We can still pass any data type we want. It is best used with third-party checkers like mypy. This has many pros including telling our co-developers much-needed information. This is called type hinting. Talking in detail about typing in python is beyond the scope of this article but one can read the official documentation here.
A type alias is simply creating an alias to a defined type. For example, we are going to be learning vectors in this article. We know that a vector is a list of numbers, preferably floating-point numbers. Hence we assign a list of floating-point numbers as a vector.
from typing import List # Do note we have capital L in List Vector = List[float]
From now onwards, we can type-hint vectors using
Vector. Third-party checkers will also take note of it.
assert keyword is used to test our code. It is used for debugging. This is best explained through an example.
def addition(num1, num2): return num1 + num2 assert addition(1, 2) == 3, "not working"g"
Here, we have defined a function
addition that takes in two values
num2. It returns
num1 + num2. We can use
assert to check if our function is working as intended. We know the sum of 1 and 2 should be 3. When we run the code, the
assert keyword runs the
addition function with 1 and 2 as arguments. Then it will check if the returned value is equal to 3. If it is, the code will work just fine. If it isn’t, we will get an assertion error “not working”. This is a useful way of testing our code. We will be using
assert in this tutorial because we want to be sure the functions we write are correct. It will be otherwise hard to detect from the returned value.
We already see how we used type alias to create the vector type. Now let’s actually create a vector.
from typing import List Vector = List[float] random_vector = [5.0, 2.0, 3.0]
Was that too simple? Well, that’s all it takes. We have defined a list of floats as a vector. So, we have successfully created our first vector. What we really need to do now is creating all the functions for this vector so we can actually do vector operations. Let’s start with vector addition.
While adding two or more vectors, we add the corresponding elements. If the vectors have uneven length, addition is not possible.
# Defining function for vector addition def vector_addition(v: Vector, w: Vector) -> Vector: # Checking if the vectors are of equal length assert len(v) == len(w), "vectors must have equal length" # Using list comprehension to sum elements of a list using index return [v_i + w_i for v_i, w_i in zip(v, w)] # Testing our function assert vector_addition([1, 2, 3], [4, 5, 6]) == [5, 7, 9]
See how we used
Vector as a type hint while defining our function. We used
assert to check if our vectors are of the same length. The
zip() creates a new list containing tuples of values having the same index in list/vector
w. Each tuple in this new list is accessed and their values are summed. One can read about list comprehensions in our pythonic programming tutorial.
The code will be similar to vector addition. Instead of adding each element, we subtract each element.
# Defining function for vector subtraction def vector_subtraction(v: Vector, w: Vector) -> Vector: # Checking if the vectors are of equal length assert len(v) == len(w), "vectors must have equal length" # Using list comprehension to sum elements of a list using index return [v_i - w_i for v_i, w_i in zip(v, w)] # Testing our function assert vector_subtraction([7, 8, 9], [4, 5, 6]) == [3, 3, 3]]
Scalar multiplication can be achieved by simply multiplying the vector with a number. It is a simple function.
# defining function for scalar multiplication def scalar_multi(c: float, v: Vector) -> Vector: return [c * v_i for v_i in v] # testing our function assert scalar_multi(5, [1, 2, 3]) == [5, 10, 15]
For finding the dot product of two vectors, we find the sum of the products of each corresponding elements. The vectors must be of equal length.
# defining function for finding dot product def dot_product(v: Vector, w: Vector) -> float: assert len(v) == len(w), "vectors must have equal length" return sum(v_i * w_i for v_i, w_i in zip(v, w)) # testing our function assert dot_product([1, 2, 3], [4, 5, 6]) == 3
sum() accepts a list of values and returns their sum. The list comprehension
v_i * w_i for v_i, w_i in zip(v, w) creates a list of the products of each corresponding elements.
A magnitude of a vector is the length of the vector. It is found out by taking the square root of the sum of squares of each direction. To find the sum of squares, all we need to do is find the dot product of a vector with itself. We already have the function for finding the dot product above. To find the sum of squares, just pass the same vector as both the arguments.
# defining function for sum of squares def sum_of_squares(v: Vector) -> float: return dot_product(v, v) # testing our function assert sum_of_squares([1, 2, 3]) == 14
Now we need to find the square root to compute magnitude.
from math import sqrt # defining function for finding magnitude def magnitude(v: Vector) -> float: return sqrt(sum_of_squares(v)) # testing our function assert magnitude([3, 4]) == 5
Distance between the two vectors is the square root of the sum of squares of differences of the corresponding elements. We already have a
magnitude function that finds the square root of the sum of squares. All we have to do is to use
vector_subtrataction function to find the difference of corresponding elements and pass it as argument to the magnitude function.
# defing function for finding distance between two vectors def distance(v: Vector, w: Vector) -> float: return magnitude(vector_subtraction(v, w)) # testing our function assert distance([1, 6], [1, 2]) == 4
In this tutorial, we briefly learned typing, type alias, and assert feature. We learned to utilize them for creating vectors in python. We also created functions for calculating vector addition, subtraction, scalar multiplication, dot product, magnitude, and for finding distance between two vectors.
We recommend using a third-party library like NumPy in your actual data science project. The library has built-in methods for defining vectors and conducting operations on them. However, we hope this tutorial helped you gain some clarity on behind the scenes working of vectors and vector operations.