user11305439
user11305439

Reputation: 117

Formatting Table in Pandas plot with table=true

I have a dataframe that I have plotted as a stacked bar chart and added a table of values below the plot using table=true. I've had to modify it slightly so its readable.

myplot=df.plot.bar(stacked=True,title=name,grid=True,fontsize = 12, table=True)
myplot.axes.get_xaxis().set_visible(False)
table = myplot.tables[0]
# Setting the font size
table.set_fontsize(10)

Output of Current Code

Is it possible to:

  1. Add another row to the table with the SUM values of each column
  2. Remove NaNs
  3. Add background color to the table

Thanks

Upvotes: 1

Views: 2891

Answers (1)

Nathan Clement
Nathan Clement

Reputation: 1203

Most of this information comes from digging around here:

  1. Table: https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.table.html
  2. Cell: https://matplotlib.org/3.1.1/api/table_api.html#matplotlib.table.Cell
  3. Text: https://matplotlib.org/3.1.1/api/text_api.html#matplotlib.text.Text

I used the strategies recommended here: Matplotlib table formatting

For a complete solution, here is my setup (slight extension of yours):

import pandas as pd
import matplotlib.pyplot as plt

data = {
    1: {'A': 50, 'B': 100, 'C': 55, 'D': 42, 'E': 55},
    2: {'A': 100, 'B': 50, 'C': None, 'D': None, 'E': None},
    3: {'A': 67, 'B': None, 'C': None, 'D': None, 'E': None},
    4: {'A': 50, 'B': None, 'C': None, 'D': None, 'E': None}
}
df = pd.DataFrame(data)
#df = df.swapaxes("index", "columns")

myplot=df.plot.bar(stacked=True,grid=True,fontsize = 12, table=True)
myplot.axes.get_xaxis().set_visible(False)
table = myplot.tables[0]
# Setting the font size
table.set_fontsize(10)

This section iterates through cells in the table, checks if the text is "nan", sets to blank if it is, and sets the color:

# iterate through cells
desiredBgColor = (0.5,0.5,0.5)
tableRowLength = len(df.columns)
tableColLength = len(df.index)
for cIx in range(1, tableColLength): # start with 1 to not include column headers
    for rIx in range(0, tableRowLength + 1): # start with 0 because apparently row index does appear in celldata
        c = table.get_celld()[(cIx, rIx)]
        cellText = c.get_text()
        if (cellText.get_text() == 'nan'):
            cellText.set_text('')
        c.set_color(desiredBgColor)

This adds a sum row:

# add a row
desiredSumRowColor = (.6, .6, .6)
cellWidth = table.get_celld()[(1, 1)].get_width() # have to check width from an existing cell
cellHeight = table.get_celld()[(1, 1)].get_height() # have to check height from an existing cell
for cIx in range(0, tableColLength):
    c = table.add_cell(tableRowLength + 1, cIx, cellWidth, cellHeight)
    c.set_color(desiredSumRowColor)
    c.set
    c.get_text().set_text(df.iloc[cIx].sum())

Final result below:

Plot Image

Upvotes: 1

Related Questions