Building a dictionary first with useful names helps to understand what is going on.

temp = {}
for year1, values1 in data.items():
    for author1, values2 in values1.items():
        for number, values3 in values2.items():
            temp.setdefault('Year1', []).append(year1)
            temp.setdefault('Author1', []).append(author1)
            temp.setdefault('No.', []).append(number)
            for key, value in values3.items():
                temp.setdefault(key, []).append(value)
print(pd.DataFrame(temp))

Output:

            Author          Author1           City  No.  \
0     Barack Obama     Barack Obama             []    1   
1     Barack Obama     Barack Obama  [Springfield]    2   
2     Barack Obama     Barack Obama      [Chicago]    3   
3  Bill Richardson  Bill Richardson             []    1   
4  Bill Richardson  Bill Richardson             []    2   
5  Bill Richardson  Bill Richardson             []    3   
6     Barack Obama     Barack Obama        [Parma]    1   
7     Barack Obama     Barack Obama     [Sandusky]    2   
8     Barack Obama     Barack Obama             []    3   



                                               Title     Type  Year  Year1  
0  Keynote Address at the 2004 Democratic Nationa...  address  2008   2008  
1  Remarks Announcing Candidacy for President in ...  remarks  2008   2008  
2       Remarks at the AIPAC Policy Forum in Chicago  remarks  2008   2008  
3  Iraq Speech to New Hampshire Democratic State ...   speech  2008   2008  
4                  Address to the DNC Winter Meeting  address  2008   2008  
5  Speech: The New Realism and the Rebirth of Ame...   speech  2008   2008  
6   535 - Remarks at a Campaign Rally in Parma, Ohio  remarks  2012   2012  
7  534 - Remarks at a Campaign Rally in Sandusky,...  remarks  2012   2012  
8  533 - Remarks at a Campaign Rally in Maumee, Ohio  remarks  2012   2012 

Our create with your desired column order:

df = pd.DataFrame(temp, columns=['Year1', 'Author1',  'No.', 'Author',
                                 'City', 'Title', 'Type', 'Year']) 
df

Answer from Mike Müller on Stack Overflow
Top answer
1 of 2
3

Building a dictionary first with useful names helps to understand what is going on.

temp = {}
for year1, values1 in data.items():
    for author1, values2 in values1.items():
        for number, values3 in values2.items():
            temp.setdefault('Year1', []).append(year1)
            temp.setdefault('Author1', []).append(author1)
            temp.setdefault('No.', []).append(number)
            for key, value in values3.items():
                temp.setdefault(key, []).append(value)
print(pd.DataFrame(temp))

Output:

            Author          Author1           City  No.  \
0     Barack Obama     Barack Obama             []    1   
1     Barack Obama     Barack Obama  [Springfield]    2   
2     Barack Obama     Barack Obama      [Chicago]    3   
3  Bill Richardson  Bill Richardson             []    1   
4  Bill Richardson  Bill Richardson             []    2   
5  Bill Richardson  Bill Richardson             []    3   
6     Barack Obama     Barack Obama        [Parma]    1   
7     Barack Obama     Barack Obama     [Sandusky]    2   
8     Barack Obama     Barack Obama             []    3   



                                               Title     Type  Year  Year1  
0  Keynote Address at the 2004 Democratic Nationa...  address  2008   2008  
1  Remarks Announcing Candidacy for President in ...  remarks  2008   2008  
2       Remarks at the AIPAC Policy Forum in Chicago  remarks  2008   2008  
3  Iraq Speech to New Hampshire Democratic State ...   speech  2008   2008  
4                  Address to the DNC Winter Meeting  address  2008   2008  
5  Speech: The New Realism and the Rebirth of Ame...   speech  2008   2008  
6   535 - Remarks at a Campaign Rally in Parma, Ohio  remarks  2012   2012  
7  534 - Remarks at a Campaign Rally in Sandusky,...  remarks  2012   2012  
8  533 - Remarks at a Campaign Rally in Maumee, Ohio  remarks  2012   2012 

Our create with your desired column order:

df = pd.DataFrame(temp, columns=['Year1', 'Author1',  'No.', 'Author',
                                 'City', 'Title', 'Type', 'Year']) 
df

2 of 2
0

Using list comprehension:

df = pd.DataFrame([[k, j, n] + [p for p in m.values()] for k, i in d.items() for j, l in i.items() for n, m in l.items()],columns=['Year', 'Author1', 'No.', 'Author', 'City', 'Title', 'Type', 'Year'])

#    df
#       Year          Author1  No.           Author           City                                                 Title     Type  Year  
#    0  2008     Barack Obama    1     Barack Obama             []     Keynote Address at the 2004 Democratic Nationa...  address  2008  
#    1  2008     Barack Obama    2     Barack Obama  [Springfield]     Remarks Announcing Candidacy for President in ...  remarks  2008  
#    2  2008     Barack Obama    3     Barack Obama      [Chicago]          Remarks at the AIPAC Policy Forum in Chicago  remarks  2008  
#    3  2008  Bill Richardson    1  Bill Richardson             []     Iraq Speech to New Hampshire Democratic State ...   speech  2008  
#    4  2008  Bill Richardson    2  Bill Richardson             []                     Address to the DNC Winter Meeting  address  2008  
#    5  2008  Bill Richardson    3  Bill Richardson             []     Speech: The New Realism and the Rebirth of Ame...   speech  2008  
#    6  2012     Barack Obama    1     Barack Obama        [Parma]     535 - Remarks at a Campaign Rally in Parma, Ohio   remarks  2012  
#    7  2012     Barack Obama    2     Barack Obama     [Sandusky]     534 - Remarks at a Campaign Rally in Sandusky,...  remarks  2012  
#    8  2012     Barack Obama    3     Barack Obama             []     533 - Remarks at a Campaign Rally in Maumee, Ohio  remarks  2012  
🌐
W3Schools
w3schools.com › python › python_dictionaries_nested.asp
Python - Nested Dictionaries
Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Practice Problems Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Training ... A dictionary can contain dictionaries, this is called nested dictionaries.
🌐
PyPI
pypi.org › project › nested_dict
nested_dict · PyPI
# nested dict of strings nd = ... dictionaries is a bit of a pain without recursion. nested dict allows you to flatten the nested levels into tuples before iteration....
🌐
Readthedocs
nested-dict.readthedocs.io
nested_dict — nested_dict 1.61 documentation
nested_dict is a drop-in replacement extending python dict and defaultdict with multiple levels of nesting. You can created a deeply nested data structure without laboriously creating all the sub-levels along the way: >>> nd= nested_dict() >>> # magic >>> nd["one"][2]["three"] = 4
🌐
Stack Overflow
stackoverflow.com › questions › 37247010 › creating-heavily-nested-python-dictionaries-in-a-clean-programmatic-way
dictionary - Creating heavily nested python dictionaries in a clean programmatic way - Stack Overflow
You can chain these as far as you want to make a nested dictionary hierarchy. For instance, here is a 2 and 3 level hierarchy dictionary. two_level = defaultdict(lambda: defaultdict(dict)) three_level = defaultdict(lambda: defaultdict(lambda: defaultdict(dict))) Your dictionary is now as follows: two_level[1][2] and three_level[1][2][3] and will be empty dicts {}. So in your case, it appears you have a 4 level nesting, so I'd probably initialize outputdict as: output_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))) Can't think of anything else you can do here - I'd recommend that you simplify this nested structure, if possible.
🌐
Medium
bond-kirill-alexandrovich.medium.com › nested-dictionaries-in-python-5a362e03ec6c
Nested dictionaries in Python. In this article I will show you what is… | by Kirill Bondarenko | Medium
June 24, 2020 - Nested dictionaries in Python In this article I will show you what is a nested dictionary and how to work with it efficient (get ,set values). Introduction How often you need to use nested dictionary …
🌐
Medium
medium.com › @ryan_forrester_ › python-nested-dictionaries-complete-guide-8a61b88a2e02
Python Nested Dictionaries: Complete Guide | by ryan | Medium
October 24, 2024 - A nested dictionary is simply a dictionary that contains other dictionaries as values. Here’s a basic example: employee = { 'name': 'Sarah Chen', 'position': { 'title': 'Senior Developer', 'department': 'Engineering', 'details': { 'level': ...
🌐
Learn By Example
learnbyexample.org › python-nested-dictionary
Python Nested Dictionary - Learn By Example
June 20, 2024 - You can access elements within a nested dictionary by specifying multiple keys in a chain, using square brackets []. Each key represents a level of nesting.
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › python-get-particular-nested-level-items-from-dictionary
Python - Get particular Nested level Items from Dictionary - GeeksforGeeks
February 7, 2025 - In this, we perform required recursion for inner nestings, and isinstance is used to differentiate between dict instance and other data types to test for nesting. ... The original dictionary is : {‘Gfg’: {‘n1’: 3, ‘nd2’: {‘n2’: 6}}, ‘is’: {‘ne1’: 5, ‘ndi2’: {‘ne2’: 8, ‘ne22’: 10}}} Required items : {‘n2’: 6, ‘ne2’: 8, ‘ne22’: 10}
Top answer
1 of 5
4

I've written this after I saw @VoNWooDSoN's answer. I turned it into an iterator instead of printing inside the function and a little bit of changes to make it more readable. So see his original answer here.

def flatten(d, base=()):
    for k, v in d.items():
        if isinstance(v, dict):
            yield from flatten(v, base + (k,))
        else:
            yield base + (k, v)

1- yielding instead of printing.

2- isinstance() instead of type so that subclasses of dict can also work. You could also use MutableMapping from typing module instead of dict to make it more generic.

3- IMO , getting (k, v) pairs from .items() is much more readable than k and d[k].

More generic ?

Do you wanna expand this to even more generic which CAN(not have to, like the solution in the OP) accept the number of depths just in case?

Consider these examples:

d_level1 = {"a": 1, "b": 2, "c": 3}
d_level2 = {"group_1": {"a": 1}, "group_2": {"b": 2, "c": 3}}
d_level3 = {"collection_1": d_level2}

for items in flatten(d_level3):
    print(items)
print('------------------------------')
for items in flatten(d_level3, depth=0):
    print(items)
print('------------------------------')
for items in flatten(d_level3, depth=1):
    print(items)
print('------------------------------')
for items in flatten(d_level3, depth=2):
    print(items)

output:

('collection_1', 'group_1', 'a', 1)
('collection_1', 'group_2', 'b', 2)
('collection_1', 'group_2', 'c', 3)
------------------------------
('collection_1', {'group_1': {'a': 1}, 'group_2': {'b': 2, 'c': 3}})
------------------------------
('collection_1', 'group_1', {'a': 1})
('collection_1', 'group_2', {'b': 2, 'c': 3})
------------------------------
('collection_1', 'group_1', 'a', 1)
('collection_1', 'group_2', 'b', 2)
('collection_1', 'group_2', 'c', 3)

depth=None doesn't consider the depth (still works like you want at the first place). But now by specifying depths from 0 to 2 you can see that we are able to iterate how deep we want. here is the code:

def flatten(d, base=(), depth=None):
    for k, v in d.items():
        if not isinstance(v, dict):
            yield base + (k, v)
        else:
            if depth is None:
                yield from flatten(v, base + (k,))
            else:
                if depth == 0:
                    yield base + (k, v)
                else:
                    yield from flatten(v, base + (k,), depth - 1)
2 of 5
3

Here's a quick and dirty solution for you:

d_level1 = {"a":1,"b":2,"c":3}
d_level2 = {"group_1":{"a":1}, "group_2":{"b":2,"c":3}}
d_level3 = {"collection_1":d_level2}

def flatten(d_in, base=()):
    for k in d_in:
        if type(d_in[k]) == dict:
            flatten(d_in[k], base+(k,))
        else:
            print(base + (k, d_in[k]))

flatten(d_level1)
# ('a', 1)
# ('b', 2)
# ('c', 3)

flatten(d_level2)
#('group_1', 'a', 1)
#('group_2', 'b', 2)
#('group_2', 'c', 3)

flatten(d_level3)
# ('collection_1', 'group_1', 'a', 1)
# ('collection_1', 'group_2', 'b', 2)
# ('collection_1', 'group_2', 'c', 3)

Be aware!! Python has a recursion limit of about 1000! So, when using recursion in python think very carefully what you're trying to do and be prepared to catch a RuntimeError if you call a recursive function like this.

EDIT: With comments I realized that I'd made a mistake where I did not add the key to the level1 dict output and that I was using a mutable structure as a default argument. I added these and parens in the print statement and reposted. The output now matches the OP's desired output and uses better and modern python.

🌐
SitePoint
sitepoint.com › python hub › nested dictionaries
Python - Nested Dictionaries | SitePoint — SitePoint
A good rule of thumb is to keep nesting to a maximum of three or four levels deep. ... When working with real-world data, you'll often need to transform simple dictionaries into more complex nested structures.
🌐
Programiz
programiz.com › python-programming › nested-dictionary
Python Nested Dictionary (With Examples)
In the above program, we assign a dictionary literal to people[4]. The literal have keys name, age and sex with respective values. Then we print the people[4], to see that the dictionary 4 is added in nested dictionary people. In Python, we use “ del “ statement to delete elements from nested dictionary.
🌐
GeeksforGeeks
geeksforgeeks.org › python-nested-dictionary
Python Nested Dictionary - GeeksforGeeks
June 10, 2023 - A nested dictionary in Python is a dictionary that contains another dictionary (or dictionaries) as its value. Updating a nested dictionary involves modifying its structure or content by:Adding new key-value pairs to any level of the nested structure.Modifying existing values associated with specifi
🌐
GeeksforGeeks
geeksforgeeks.org › python › three-level-nested-dictionary-python
Three Level Nested Dictionary Python - GeeksforGeeks
July 23, 2025 - In Python, a dictionary is a collection of key-value pairs, and it can contain other dictionaries as values. When you have a dictionary within another dictionary, and then another dictionary within the inner dictionary, you have a 3-level nested dictionary.
🌐
LearnModernPython
learnmodernpython.com › home › mastering python nested dictionaries: the comprehensive guide
Mastering Python Nested Dictionaries: The Comprehensive Guide
April 7, 2026 - Recursion: Recursion is the most powerful way to process dictionaries of arbitrary depth. Optimization: For massive nested data, consider specialized libraries like Pandas or using Classes to maintain data integrity. Technically, the depth is limited only by your computer’s memory and Python’s recursion limit (typically 1000). However, for practical readability and performance, nesting beyond 4 or 5 levels ...
🌐
Betterdatascience
betterdatascience.com › nested-dictionary-python
Nested Dictionary Python - A Complete Guide to Python Nested Dictionaries | Better Data Science
April 18, 2023 - Today you’ll learn what is a nested dictionary, why to use nested dictionaries in Python, how to loop through a nested dictionary in Python, and much more.
🌐
TutorialsPoint
tutorialspoint.com › article › python-get-particular-nested-level-items-from-dictionary
Python - Get particular Nested level Items from Dictionary
Dictionaries in Python allow you to store key-value pairs, making it easy to organize and access data efficiently. Sometimes, we may need to retrieve specific items from nested levels within a dictionary. We can use recursion, isinstance() with recursion, and dict.get() methods to extract nested-level items from dictionaries.
🌐
pythontutorials
pythontutorials.net › blog › loop-through-all-nested-dictionary-values
How to Loop Through All Nested Dictionary Values in Python (Any Number of Levels) — pythontutorials.net
To avoid recursion depth limits, use an iterative approach with a stack. A stack (LIFO: Last-In-First-Out) lets you manually track nested dictionaries to traverse, mimicking recursion without function calls. Initialize a stack with the top-level dictionary.