How to subtract values from two dictionaries in python

Category: Programming, Python | July 15, 2023

A dictionary or dict is one of the data types of Python under the mapping type category. It stores items separated by commas, where each item is composed of a key:value pair format. Keys must be unique. This type is particularly useful in data storage and retrieval. We store the value with a key and retrieve the value by a given key.

The value in a dict can be updated. To access the value, we can use value by index, get() and items() methods. In this article, I will discuss subtraction of values from two dictionaries when their keys are the same. I will use subtraction to update the data of one dict.

You may go to section D directly to see the three methods with codes on how subtraction is done. There is also a benchmark result in section E which compares the speed of these methods.

What is a dictionary

A dictionary or dict is a Python data type that can act as an item container. The so called item is of the form key:value. Keys of a dict must be unique. You can create a dict by placing the items, separated by commas, inside the braces {} or with the use of dict constructor.

Here are some examples of a dict.

capitals = {"USA": "Washington D.C.", "China": "Beijing", "Japan": "Tokyo"}
submarines = {"USA": 69, "North Korea": 72, "China": 74}
skill_level = {0: "novice", 1: "expert", 2: "Master"}
location = {(13, 122): "Philippines", (12, 18): "Angola", (25, 51): "Qatar"}
population = dict(usa=331002651, russia=145934462, china=1439323776, australia=25499884)

The "USA": "Washington D.C." and similar form is called the item of a dict, where “USA” is the key and “Washington D.C.” is the value. The key and value are separated by a colon :.

The value in a dict is not limited to an integer or string, it can also be a list, tuple or even another dict. Here is an example with dict value.

code

country_info = {
  "USA": {"population":331002651, "land area": 9147420},
  "China": {"population":1439323776, "land area": 9388211}
}

# Get the land area of China.
china_land_area = country_info["China"]["land area"]
print(f"china land area: {china_land_area}")

output

china land area: 9388211

How to access the value of a key in a dictionary

There are some ways to get the value of a key in a dictionary. I will only show the most common three. Access by index or bracket notation, by get(), and by items() method.

Access the value by its index

A dict value can be accessed through its index. The index of a dict is its key. Given a submarines dict, print the value for key “USA”.

code

submarines = {"USA": 69, "North Korea": 72, "China": 74}

# Get number of submarines for USA.
usa_submarines = submarines["USA"]
print(f"USA has {usa_submarines} number of submarines.")

output

USA has 69 number of submarines.

One disadvantage of using an index to get the value is when the key is not in the dict. For example try to get the value for Japan.

code

submarines = {"USA": 69, "North Korea": 72, "China": 74}

# Get number of submarines for Japan.
japan_submarines = submarines["Japan"]
print(f"Japan has {japan_submarines} number of submarines.")

output

Traceback (most recent call last):
  japan_submarines = submarines["Japan"]
KeyError: 'Japan'

We got an error because Japan key is not in a submarines dict. To solve this error we can check if the key is in the dictionary.

code

submarines = {"USA": 69, "North Korea": 72, "China": 74}

# Get number of submarines for Japan.
if "Japan" in submarines:
    japan_submarines = submarines["Japan"]
    print(f"Japan has {japan_submarines} number of submarines.")
else:
    print(f"Japan key is not in the dictionary.")

output

Japan key is not in the dictionary.

And so we have not encountered the KeyError exception.

The other way is to use the get() method of dict which is discussed in the following section.

Access the value by get() method

dict.get(key[, default])

Another way of getting the value of a dict without encountering a KeyError is by using the get() method.

The class dict has a get() method that returns the value when a key is given. If the key is not found, default will be returned. If default is not specified None will be returned.

Here is an example of how to use get().

code

covid_cases = {"UK": 24618436, "Taiwan": 10239998, "USA": 107249019}

# Get the value of Taiwan.
taiwan_cases = covid_cases.get("Taiwan", 0)
print(f"taiwan covid cases: {taiwan_cases}")

# Get the value of Philippines
phi_cases = covid_cases.get("Philippines")
print(f"phi covid cases: {phi_cases}")

# Get the value of Japan
japan_cases = covid_cases.get("Japan", "not found in dict")
print(f"japan covid cases: {japan_cases}")

output

taiwan covid cases: 10239998
phi covid cases: None
japan covid cases: not found in dict

Access the value by items() method

dict.items()

The items() method parses the items inside the given dict one by one. Here is an example of how to use this method.

code

# Print all the keys and corresponding values.
skill_level = {0: "novice", 1: "expert", 2: "Master"}
for k, v in skill_level.items():
    print(f"key: {k}, value: {v}")

output

key: 0, value: novice
key: 1, value: expert
key: 2, value: Master

Why subtract two dictionaries

The concept behind dictionary subtraction is data updating. In this process, the minuend receives modifications after applying the subtrahend. We apply subtraction of value if the key in subtrahend and minuend is the same.

difference = minuend - subtrahend

Account deposit update

One application of dictionary subtraction is in the banking sector. People create bank accounts and make deposits, do some withdrawals and other transactions. You can create a balance dict with keys as names and deposits as values.

Let us create an example.

balance = {"Joe Demm Rkuss": 1200, "Walter Simdol": 900, "Roger ZeMayan": 3500}

After one week, Roger withdrew 500. Let us make another dict to represent this activity.

withdraw = {"Roger ZeMayan": 500}

If we are going to update the balance now, it is practical to just subtract withdraw (subtrahend) from balance (minuend).

The updated balance is then:

balance = {"Joe Demm Rkuss": 1200, "Walter Simdol": 900, "Roger ZeMayan": 3000}

We only subtract values if their keys are the same.

Rating update

Yet another example is updating of players’ chess rating after an unfavorable tournament result.

classical_rating = {"Carlsen, Magnus": 2853, "Firouzja, Alireza": 2786, "Ding, Liren": 2780,
                   "Nepomniachtchi, Ian": 2779}
penalty = {"Carlsen, Magnus": 18.3, "Firouzja, Alireza": 9.1, "Ding, Liren": 0,
                   "Nepomniachtchi, Ian": 0}

After subtraction we have the updated classical rating.

classical_rating = {"Carlsen, Magnus": 2834.7, "Firouzja, Alireza": 2776.9, "Ding, Liren": 2780,
                   "Nepomniachtchi, Ian": 2779}

Different methods to subtract two dictionaries

Let us define our two dictionaries, one is the minuend and the second is the subtrahend.

minuend

balance = {"Johnny Doegh": 572, "Jhane Smithrol": 264, 'Michael Borrissy': 356}

subtrahend

withdrawals = {"Johnny Doegh": 80, "Rommy Smithrol": 12}

difference

updated_balance = balance - withdrawals

Method 1

It uses a for loop to scan each item in the withdrawals with the use of dict items() method. Subtract the withdrawal value from balance value if the key in withdrawals and balance dictionaries are the same.

filename: method1.py

code

def method1(balance: dict, withdrawals: dict):
    """Subtracts withdrawals from balance by for loop.

    Updates the values in balance if key is found in withdrawals. The
    value in balance will be subtracted by the value in withdrawal if
    their keys are the same. Only the balance will be updated,
    withdrawals will not be changed.

    Args:
      balance: A dict to be updated as minuend.
      withdrawals: A dict as subtrahend.

    Returns:
      The updated balance after subtraction of values.
    """
    # Parse each item in withdrawals.
    for key, value in withdrawals.items():
        # Check if key is in the balance.
        if key in balance:
            balance[key] -= value  # update the value
    return balance


def main():
    # The given two dictionaries. init_balance is the minuend
    # while withdrawals is the subtrahend.
    init_balance = {"Johnny Doegh": 572, "Jhane Smithrol": 264,
                    'Michael Borrissy': 356}
    withdrawals = {"Johnny Doegh": 80, "Rommy Smithrol": 12}

    print('Method 1: Using items method, value by index, "for" loop and "in" operator.')
    balance = init_balance.copy()
    new_balance = method1(balance, withdrawals)
    print(f"initial balance: {init_balance}")
    print(f"withdrawals: {withdrawals}")
    print(f"new balance: {new_balance}")


if __name__ == '__main__':
    main()

output

Method 1: Using items method, value by index, "for" loop and "in" operator.
initial balance: {'Johnny Doegh': 572, 'Jhane Smithrol': 264, 'Michael Borrissy': 356}
withdrawals: {'Johnny Doegh': 80, 'Rommy Smithrol': 12}
new balance: {'Johnny Doegh': 492, 'Jhane Smithrol': 264, 'Michael Borrissy': 356}

The common key is “Johnny Doegh”. It has an initial balance of 572. He withdrew 80, so the difference is 572 – 80 or 492. In the new balance, “Johnny Doegh” has only 492. Other values in the initial balance remain the same.

Method 2

It uses a dict comprehension along the balance and subtract the withdrawals with get() method and if key is not found, zero will be subtracted which will not affect the balance. A new balance is created by subtracting the withdrawals from the current value in the balance for each key.

filename: method2.py

code

def method2(balance: dict, withdrawals: dict):
    """Subtracts withdrawals from balance by dict comprehension."""
    new_balance = {key: balance[key] - withdrawals.get(key, 0) for key in balance}
    return new_balance


def main():
    # The given two dictionaries. init_balance is the minuend
    # while withdrawals is the subtrahend.
    init_balance = {"Johnny Doegh": 572, "Jhane Smithrol": 264,
                    'Michael Borrissy': 356}
    withdrawals = {"Johnny Doegh": 80, "Rommy Smithrol": 12}

    print("Method 2: Using dict comprehension, with get method and value by index.")
    balance = init_balance.copy()
    new_balance = method2(balance, withdrawals)
    print(f"initial balance: {init_balance}")
    print(f"withdrawals: {withdrawals}")
    print(f"new balance: {new_balance}")


if __name__ == '__main__':
    main()

output

Method 2: Using dict comprehension, with get method and value by index.
initial balance: {'Johnny Doegh': 572, 'Jhane Smithrol': 264, 'Michael Borrissy': 356}
withdrawals: {'Johnny Doegh': 80, 'Rommy Smithrol': 12}
new balance: {'Johnny Doegh': 492, 'Jhane Smithrol': 264, 'Michael Borrissy': 356}

Method 3

Like method 2 having dict comprehension, but along the withdrawals dict. It uses an if condition to check if a key from withdrawals is present in balance dict and if so, execute the subtraction and use a dict update method to update the balance.

filename: method3.py

code

def method3(balance: dict, withdrawals: dict):
    """Subtracts withdrawals from balance by update() and dict comprehension."""
    balance.update({key: balance.get(key, 0) - value for key, value in withdrawals.items() if key in balance})
    return balance


def main():
    # The given two dictionaries. init_balance is the minuend
    # while withdrawals is the subtrahend.
    init_balance = {"Johnny Doegh": 572, "Jhane Smithrol": 264,
                    'Michael Borrissy': 356}
    withdrawals = {"Johnny Doegh": 80, "Rommy Smithrol": 12}

    print("Method 3: Using dict comprehension with update, get and items methods.")
    balance = init_balance.copy()
    new_balance = method3(balance, withdrawals)
    print(f"initial balance: {init_balance}")
    print(f"withdrawals: {withdrawals}")
    print(f"new balance: {new_balance}")


if __name__ == '__main__':
    main()

output

Method 3: Using dict comprehension with update, get and items methods.
initial balance: {'Johnny Doegh': 572, 'Jhane Smithrol': 264, 'Michael Borrissy': 356}
withdrawals: {'Johnny Doegh': 80, 'Rommy Smithrol': 12}
new balance: {'Johnny Doegh': 492, 'Jhane Smithrol': 264, 'Michael Borrissy': 356}

Performance comparisons

Let us check each method and measure the time it takes to update a given balance when withdrawals are applied. The test is consisting of 5 million items for balance dict and 5000 items for withdrawals dict.

The benchmarking is done on i7-2600K processor.

output

balance: 5000000 items, withdrawals: 5000 items

    Methods  ElapseSec
0  Method 1      0.003
1  Method 2      3.130
2  Method 3      0.149

The difference is only small except for method 2. Method 1 is the fastest. Methods 1 and 3 just update the input data while method 2 creates a new balance from the given input. Updating is faster than creating new items.

Summary

A Python dictionary, also known as a dict, serves as a collection of elements or items. Each item in the dictionary consists of a pair, referred to as a key:value pair. To create a dictionary, these items must be separated in commas and must be enclosed within the braces {}. One significant characteristic of a dictionary is that its keys are unique.

The values in a dict can be accessed by index or bracket notation. In addition, the get() and items() methods can also be used to access the values. Subtraction of dictionary values requires knowledge on how to access its values. We subtract one dictionary value from another dictionary value if the key is the same to update the value of the latter dictionary.

Method 1 is the fastest of the 3 methods presented, after a test of 5 million items of dict. It loops on the subtrahend dict using items() method, check the key in the minuend dict and update the minuend if a key is found. It is fast because the number of items in the subtrahend is usually lesser than that of the minuend. It also just update the input dict instead of creating a new output as in method 2.