Introduction

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.

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.

vector.png

The above vector is in a 2D plane. We can however represent vectors in any number of dimensions, except 1D.

Representing our data in vector format

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.

Typing

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.

Type alias

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

The 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 num1 and 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.

Creating a vector

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.

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 v and 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.

Vector subtraction

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

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]

Dot product

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

The 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.

Finding magnitude

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

Finding the distance between two vectors

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

Conclusion

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.

Written by Aravind Sanjeev, an India-based blogger and web developer. Read all his posts. You can also find him on twitter.