Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print Nested Dictionary in Table Format

I am trying to print my nested dictionary in a table format. But have not been able to do so. The table is a list of student names and student grades. I would like it to be in a "Report Card" type format that is easy to read. The for loop I am using prints out the results. But it is one column list form.

This is my current dictionary I have setup.

student = {
    "student1": {
        "Name": "Eddy",
        "Grade": 1,
        "Math": 78,
        "English": 65,
        "Physics": 89,
        "Chemistry": 80
    },
    "student2": {
        "Name": "Jim",
        "Grade": 2,
        "Math": 89,
        "English": 65,
        "Physics": 87,
        "Chemistry": 76

    },
    "student3": {
        "Name": "Jane",
        "Grade": 3,
        "Math": 87,
        "English": 97,
        "Physics": 75,
        "Chemistry": 64

    },
}

This is the for loop I am currently using.

for i in student:
    for j in student[i]:
        print(j + " : " + str(student[i][j]))
    print("===========")

I would like to print out in a table format.

Name Grade Math English Physics Chemistry
Eddy   1    78      65     89        80
Jim    2    89      65     87        76
Jane   3    87      97     75        64

I have tried to use the format() function but could not make it work with the nested dictionary.

I also tried using pandas and converting to a pd.DataFrame, but could not make it work.

like image 899
PythonCoder1981 Avatar asked Sep 03 '25 16:09

PythonCoder1981


2 Answers

First: print() as default add new line at the end so if you want to display in one line then you have to use print(..., end="")


I think you should learn string formatting - see page pyFormat.info. This way you can better control elements in row then using spaces or \t.

It needs to work with all elements at once instead of using internal for-loop but this gives better control and needs simpler code.

for stud, val in student.items():
    print("{:4} {:^5} {:^4} {:^7} {:^7} {:^9}".format(val["Name"], val["Grade"], val["Math"], val["English"], val["Physics"], val["Chemistry"]))

I use items() to get all values for one studen and later use val["Name"], val["Grade"}, etc. so I'm sure I put values in correct order.

I use {} to define where to put element in string, and using {:^5} I define that it should use field which has 5 chars (it will add spaces if text is shorter) and ^ means it should center value in this field.

Name Grade Math English Physics Chemistry
Eddy   1    78    65      89       80    
Jim    2    89    65      87       76    
Jane   3    87    97      75       64 

In string formatting you can use {} with any other text to decoreate table. For example you can put | between fields to create

+------+-------+------+---------+---------+-----------+
| Name | Grade | Math | English | Physics | Chemistry |
+------+-------+------+---------+---------+-----------+
| Eddy |   1   |  78  |   65    |   89    |    80     |
| Jim  |   2   |  89  |   65    |   87    |    76     |
| Jane |   3   |  87  |   97    |   75    |    64     |
+------+-------+------+---------+---------+-----------+

student = {
    "student1": {
        "Name": "Eddy",
        "Grade": 1,
        "Math": 78,
        "English": 65,
        "Physics": 89,
        "Chemistry": 80
    },
    "student2": {
        "Name": "Jim",
        "Grade": 2,
        "Math": 89,
        "English": 65,
        "Physics": 87,
        "Chemistry": 76

    },
    "student3": {
        "Name": "Jane",
        "Grade": 3,
        "Math": 87,
        "English": 97,
        "Physics": 75,
        "Chemistry": 64

    },
}

print('Name Grade Math English Physics Chemistry')

for stud, val in student.items():
    print("{:4} {:^5} {:^4} {:^7} {:^7} {:^9}".format(val["Name"], val["Grade"], val["Math"], val["English"], val["Physics"], val["Chemistry"]))

print('+------+-------+------+---------+---------+-----------+')
print('| Name | Grade | Math | English | Physics | Chemistry |')
print('+------+-------+------+---------+---------+-----------+')

for stud, val in student.items():
    print("| {:4} | {:^5} | {:^4} | {:^7} | {:^7} | {:^9} |".format(val["Name"], val["Grade"], val["Math"], val["English"], val["Physics"], val["Chemistry"]))

print('+------+-------+------+---------+---------+-----------+')

BTW: to make it more universal you could use list 'Name', 'Grade', 'Math', 'English', 'Physics', 'Chemistry'] to decide which values display. You could also need code which calculate width for columns but it would be more complex code.

like image 105
furas Avatar answered Sep 05 '25 14:09

furas


Here is a pandas solution, as you mentioned unsuccessfully trying pandas. You can use pandas.DataFrame.from_dict with orient=index.

import pandas as pd

df = pd.DataFrame.from_dict(student, orient='index').reset_index(drop=True)

You get

    Name    Grade   Math    English Physics Chemistry
0   Eddy    1       78      65      89      80
1   Jim     2       89      65      87      76
2   Jane    3       87      97      75      64

For a markdown table

  • Use pandas.DataFrame.to_markdown()
print(df.to_markdown(index=False))

| Name   |   Grade |   Math |   English |   Physics |   Chemistry |
|:-------|--------:|-------:|----------:|----------:|------------:|
| Eddy   |       1 |     78 |        65 |        89 |          80 |
| Jim    |       2 |     89 |        65 |        87 |          76 |
| Jane   |       3 |     87 |        97 |        75 |          64 |
  • The benefit of pandas over other implementations, is the data is now in a format for easy analysis and plotting.
import matplotlib.pyplot as plt

df.plot.barh(x='Name', y=['Math', 'English', 'Physics', 'Chemistry'], figsize=(6, 8))
plt.xlabel('Score')
plt.legend(title='Subject', bbox_to_anchor=(1.05, 1), loc='upper left')

enter image description here

like image 44
Vaishali Avatar answered Sep 05 '25 14:09

Vaishali