Matplotlib Table- Assign different text alignments to different columns
Question:
I am creating a two column table and want the text to be as close as possible. How can I specify that the first column be right aligned and the second be left aligned?
I’ve tried by setting the general cellloc to one side (cellloc sets the text alignment)
from matplotlib import pyplot as plt
data = [['x','x'] for x in range(10)]
bbox = [0,0,1,1]
tb = plt.table(cellText = data, cellLoc='right', bbox = bbox)
plt.axis('off') # get rid of chart axis to only show table
Then looping through cells in the second columns to set them to left align:
for key, cell in tb.get_celld().items():
if key[1] == 1: # if the y value is equal to 1, meaning the second column
cell._text.set_horizontalalignment('left') # then change the alignment
This loop immediately above has no effect, and the text remains right aligned.
Am I missing something? Or is this not possible?
EDIT
A workaround is for me to separate the data into two different lists, one for each column. This produces the results I’m looking for, but I’d like to know if anyone knows of another way.
data_col1 = [xy[0] for xy in data]
data_col2 = [xy[1] for xy in data]
tb = plt.table(cellText = data_col2, rowLabels=data_col1, cellLoc='left', rowLoc='right', bbox = bbox)
Answers:
Instead of setting the alignment of the text itself, you need to set the position of the text inside the table cell. This is determined by the cell’s ._loc
attribute.
def set_align_for_column(table, col, align="left"):
cells = [key for key in table._cells if key[1] == col]
for cell in cells:
table._cells[cell]._loc = align
Some complete example:
from matplotlib import pyplot as plt
data = [['x','x'] for x in range(10)]
bbox = [0,0,1,1]
tb = plt.table(cellText = data, cellLoc='right', bbox = bbox)
plt.axis('off') # get rid of chart axis to only show table
def set_align_for_column(table, col, align="left"):
cells = [key for key in table._cells if key[1] == col]
for cell in cells:
table._cells[cell]._loc = align
set_align_for_column(tb, col=0, align="right")
set_align_for_column(tb, col=1, align="left")
plt.show()
(The approach used here is similar to changing the cell padding as in this question: Matplotlib Text Alignment in Table)
Another possible solution would be to use the method get_celld()
of your table which returns a dictionary of matplotlib.table.CustomCell
objects which you can then loop through and change in a similar way that @ImportanceOfBeingErnest’s answer does:
from matplotlib import pyplot as plt
data = [['x','x'] for x in range(10)]
bbox = [0,0,1,1]
tb = plt.table(cellText = data, cellLoc='right', bbox = bbox)
plt.axis('off')
cells = tb.get_celld()
for i in range(0, len(data)):
cells[i, 1]._loc = 'left' # 0 is first column, 1 is second column
plt.show()
Which will give the same result.
3000 views and 4 years later, things might have changed a bit.
In matplotlib 3.3.3 (tested) 3.6 (docs) accessing the cells is much simpler than the code above, as the table can be addressed as a list directly:
cell = table[row_number,column_number]
Also the function _text.set_horizontalalignment(‘left’) which is reported as not working above, now seems to work. However setting _loc sets _loc but seems to have no effect on the display (according to doc 3.6, it should) but it does not seem to do any harm.
My belt and braces code to setting column col to left alignment is
for i in range(0,nrows)
tb[i, col]._loc = 'left'
tb[i, col]._text.set_horizontalalignment('left')
Thanks to the contributors above for getting me on the right track
I am creating a two column table and want the text to be as close as possible. How can I specify that the first column be right aligned and the second be left aligned?
I’ve tried by setting the general cellloc to one side (cellloc sets the text alignment)
from matplotlib import pyplot as plt
data = [['x','x'] for x in range(10)]
bbox = [0,0,1,1]
tb = plt.table(cellText = data, cellLoc='right', bbox = bbox)
plt.axis('off') # get rid of chart axis to only show table
Then looping through cells in the second columns to set them to left align:
for key, cell in tb.get_celld().items():
if key[1] == 1: # if the y value is equal to 1, meaning the second column
cell._text.set_horizontalalignment('left') # then change the alignment
This loop immediately above has no effect, and the text remains right aligned.
Am I missing something? Or is this not possible?
EDIT
A workaround is for me to separate the data into two different lists, one for each column. This produces the results I’m looking for, but I’d like to know if anyone knows of another way.
data_col1 = [xy[0] for xy in data]
data_col2 = [xy[1] for xy in data]
tb = plt.table(cellText = data_col2, rowLabels=data_col1, cellLoc='left', rowLoc='right', bbox = bbox)
Instead of setting the alignment of the text itself, you need to set the position of the text inside the table cell. This is determined by the cell’s ._loc
attribute.
def set_align_for_column(table, col, align="left"):
cells = [key for key in table._cells if key[1] == col]
for cell in cells:
table._cells[cell]._loc = align
Some complete example:
from matplotlib import pyplot as plt
data = [['x','x'] for x in range(10)]
bbox = [0,0,1,1]
tb = plt.table(cellText = data, cellLoc='right', bbox = bbox)
plt.axis('off') # get rid of chart axis to only show table
def set_align_for_column(table, col, align="left"):
cells = [key for key in table._cells if key[1] == col]
for cell in cells:
table._cells[cell]._loc = align
set_align_for_column(tb, col=0, align="right")
set_align_for_column(tb, col=1, align="left")
plt.show()
(The approach used here is similar to changing the cell padding as in this question: Matplotlib Text Alignment in Table)
Another possible solution would be to use the method get_celld()
of your table which returns a dictionary of matplotlib.table.CustomCell
objects which you can then loop through and change in a similar way that @ImportanceOfBeingErnest’s answer does:
from matplotlib import pyplot as plt
data = [['x','x'] for x in range(10)]
bbox = [0,0,1,1]
tb = plt.table(cellText = data, cellLoc='right', bbox = bbox)
plt.axis('off')
cells = tb.get_celld()
for i in range(0, len(data)):
cells[i, 1]._loc = 'left' # 0 is first column, 1 is second column
plt.show()
Which will give the same result.
3000 views and 4 years later, things might have changed a bit.
In matplotlib 3.3.3 (tested) 3.6 (docs) accessing the cells is much simpler than the code above, as the table can be addressed as a list directly:
cell = table[row_number,column_number]
Also the function _text.set_horizontalalignment(‘left’) which is reported as not working above, now seems to work. However setting _loc sets _loc but seems to have no effect on the display (according to doc 3.6, it should) but it does not seem to do any harm.
My belt and braces code to setting column col to left alignment is
for i in range(0,nrows)
tb[i, col]._loc = 'left'
tb[i, col]._text.set_horizontalalignment('left')
Thanks to the contributors above for getting me on the right track