9. Dictionaries#

Today…dictionaries. WTOP Ch 6

A dictionary (or dict) is another container type, like a list or a tuple. Unlike lists and tuples, dictionaries are unordered, meaning we cannot index an item in the dictionary by number. Instead, dictionaries map values to descriptive strings (or numbers, but usually words) called keys, a key:value pair.

We create a dictionary in one of two ways:

myDict = dict(key1 = value1,
            key2 = value2,
            ...
            )

or

myDict = {'key1':value1,
        'key2':value2,
        ...
        }

Let’s look at an example of a dictionary called student that contains information about a particular student.

student_a = dict(first = 'Eatai',
               last = 'Roth',
               id = 1112222,
               major = 'undeclared',
               minor = 'Data Science')

student_b = {'first':'Eatai',
           'last':'Roth',
           'id':1112222,
           'major':'undeclared',
           'minor':'Data Science'}
student_a==student_b
True

A dictionary is indexed by keyword instead of position. For example:

student_a['first'] = 'Prof'
student_a
{'first': 'Prof',
 'last': 'Roth',
 'id': 1112222,
 'major': 'undeclared',
 'minor': 'Data Science'}
student_a['ssn']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[5], line 1
----> 1 student_a['ssn']

KeyError: 'ssn'

If you don’t know what keys are in a dictionary, you can ask using .keys() and similarly for values using .values()

student_a.keys()
dict_keys(['first', 'last', 'id', 'major', 'minor'])
student_a.values()
dict_values(['Prof', 'Roth', 1112222, 'undeclared', 'Data Science'])

And you can reassign values or even add fields to a dictionary on the fly.

student_a['ssn'] = 5555555555
student_a
{'first': 'Prof',
 'last': 'Roth',
 'id': 1112222,
 'major': 'undeclared',
 'minor': 'Data Science',
 'ssn': 5555555555}
student_c = {}

student_c['first'] = 'James'
student_c['last'] = 'Jameson'
student_c['email'] = 'jamesja01@gettysburg.edu'
student_c
{'first': 'James', 'last': 'Jameson', 'email': 'jamesja01@gettysburg.edu'}

Why use dictionaries?

Dictionaries are a good way to group variables or parameters that are related.

  • they can contain anything, even other dictionaries, lists, tuples

  • referencing is intuitive (you don’t have to remember where a variable is)

  • can save a single container variable rather than ??? individual variables

  • can pass multiple variables into a function as inputs

'''
Let's pass a dictionary to a function. 
Why would we use this?
'''
"\nLet's pass a dictionary to a function. \nWhy would we use this?\n"
def contactInfo(first, last, email):
    print(f'{first} {last}  can be reached at {email}')

# This is the clunky way    
contactInfo(student_c['first'], student_c['last'], student_c['email'])
James Jameson  can be reached at jamesja01@gettysburg.edu

9.1. Unpacking dictionaries.#

The contacts of a dictionary can be ‘unpacked’ into a list of key-value pairs. We can use this fun trick to store all the arguments to a function as a dictionary.

Caution: The keys of the dict must be the same as the argument names of the function.

contactInfo(**student_c)   # ** means unpack

# same as contactInfo(first = 'James', last = 'Jameson', email = 'jamesja01@gettysburg.edu')
James Jameson  can be reached at jamesja01@gettysburg.edu

We can also create functions that take dictionaries as inputs.

def contactInfo(student):
        print(f'{student['first']} {student['last']}  can be reached at {student['email']}')
        
contactInfo(student_c)
James Jameson  can be reached at jamesja01@gettysburg.edu

9.2. Lists of dicts and Dicts of lists#

If we have many dicts of the same format, we might want to package them together. We can do this as a list of dicts or a dict of lists.

  • lists of dicts are easy and convenient

  • dicts of lists are common when exporting data or creating Pandas DataFrames (foreshadowing)

    • the key will be the column name

    • the list or array will be the data

'''list of dicts - my prefered'''
student_list = [student_a,
                student_b,
                student_c]

'''dicts of lists - common in exporting data, e.g. column'''
student_dict = {} #an empty dictionary
for key in student_a.keys():
    student_dict[key] = [s[key] if key in s.keys() else None for s in student_list ]

The difference in indexing depends on whether the dict is in the list or the list is in the dict.

The outermost container is indexed first. Think, “My pajamas are in the guest bedroom, the dresser on the right, bottom drawer.” The description goes from outermost container (guest bedroom) to inner-most container (bottom drawer).

  • list of dicts - index the position within the list then the key within the dictionary

  • dict of lists - index the key within the dictionary then the position within the list (column then row)

student_list[1]['id']
1112222
student_dict['id'][1]
1112222