Ashley Adams
Ashley Adams

Reputation: 95

How to add subplot table to right of graph

I am wanting to combine a table and a horizontal bar graph, so you can see a note from the table that goes with the bar in the bar graph.

What I have now looks like this:enter image description here

I am wanting to just add one column to the right of the graph from Catalyst = in my code to get something that looks like this (Maybe more obvious in presentation the rows go with the bars): enter image description here I assume this would be done with a call to subplots. I have been having a bit of trouble with getting the second subplot to be a table, so I'm a bit confused on how to execute this. Here is my watered down code:

import matplotlib
from matplotlib import pyplot as plt
import pandas as pd 
import numpy as np

x = [u'Rimegepant',u'Rimegepant',u'Zavegepant',u'Zavegepant',u'Troriluzole',u'Troriluzole',u'Troriluzole',u'Verdiperstat',u'Verdiperstat']

y = [4,3,3,3,2,3,3,3,3]

Disease = ['Acute Treatment of Migraine','Preventive Treatment of Migraine','Acute and Preventive Migraine','Lung Inflammation COVID-19',"Alzheimer's Disease", "OCD", "Spinocerebellar Ataxia", "Multiple System Atrophy", "Amyotrophic Lateral Sclerosis"]
Catalyst = ["asdjfhskjdfhksdhf", "sdklfhslkijflk", "slkdjflskjf", "sikdjifliskjflissdofjlskdjf", "skdfjsolidjfhsoidfhjoslif","skdfhlskdhjfskldjflksjdflsk", "skidfhslikdjhfislkdjflskdfnlskdjflsk", "skdjfhlskdjlfksjdflksdjflskdjflskdjflskdjflksdjlkfnslkfnslkdfn"]


fig, ax1 = plt.subplots()    
width = 0.75 # the width of the bars 
ind = np.arange(len(y))  # the x locations for the groups
ax1.barh(ind, y, width, color="green", align='edge')
ax1.set_yticks(ind+width/2)
ax1.set_yticklabels(x, minor=False)
plt.xticks(np.arange(5),('Pre-clinical','Phase I','Phase II','Phase III', 'Approved'))
plt.margins(0,0.05)
plt.title('BHVN')
plt.ylabel('Drug')
for bar, disease in zip(ax1.patches, Disease[::-1]):
    ax1.text(0.1, bar.get_y()+bar.get_height()/2, disease, color = 'white', ha = 'left', va = 'center') 

plt.show()

Upvotes: 0

Views: 452

Answers (2)

r-beginners
r-beginners

Reputation: 35135

To add a table to the right side of the graph, set the loc attribute of ax.table() to the right side. After that, the height of the cell is specified according to the left item. Next, adjust the placement with bbox since they are overlapping. The tightness is added as an annotation.

import matplotlib
from matplotlib import pyplot as plt
import pandas as pd 
import numpy as np

x = [u'Rimegepant',u'Rimegepant',u'Zavegepant',u'Zavegepant',u'Troriluzole',u'Troriluzole',u'Troriluzole',u'Verdiperstat',u'Verdiperstat']
y = [4,3,3,3,2,3,3,3,3]

Disease = ['Acute Treatment of Migraine','Preventive Treatment of Migraine','Acute and Preventive Migraine','Lung Inflammation COVID-19',"Alzheimer's Disease", "OCD", "Spinocerebellar Ataxia", "Multiple System Atrophy", "Amyotrophic Lateral Sclerosis"]
Catalyst = ["Approved on Feb 27, 2020",
            "sNDA submitted in Oct 2020, PDUFA goal date 2Q 2021",
            "Primary and study completion expected Mar 1, 2021",
            "Expected completion April 2021",
            "Topline data 1Q2021, Study completion Jan 23, 2022",
            "Phase III completion Mar 2023",
            "Estimated completion Nov 30, 2021",
            "Primary completion Oct 20, 2021, Study completion Sep 20, 2022",
            "Primary completion Oct 2021, Study completion Nov 2022"]

tbl_cnt = [[c] for c in Catalyst]

fig, ax1 = plt.subplots()    
width = 0.75 # the width of the bars 
ind = np.arange(len(y))  # the x locations for the groups
ax1.barh(ind, y, width, color="green", align='edge')
ax1.set_yticks(ind+width/2)
ax1.set_yticklabels(x, minor=False)
plt.xticks(np.arange(5),('Pre-clinical','Phase I','Phase II','Phase III', 'Approved'))
plt.margins(0,0.05)
plt.title('BHVN')
plt.ylabel('Drug')
for bar, disease in zip(ax1.patches, Disease[::-1]):
    ax1.text(0.1, bar.get_y()+bar.get_height()/2, disease, color = 'white', ha = 'left', va = 'center') 

rtable = ax1.table(cellText=tbl_cnt, cellLoc='left', loc='right', bbox=[1.05,0,1.0,1], edges='horizontal')
ax1.text(1.3,0.9,'Catalyst', transform=fig.transFigure)

cellDict = rtable.get_celld()
for i in range(0,len(Catalyst)):
    cellDict[(i,0)].set_height(0.11)
        
plt.show()

enter image description here

Upvotes: 1

pakpe
pakpe

Reputation: 5479

Instead of including a table in your plot, create a second (twin) y-axis on the right and set the yticklabels of that axis to the Catalyst list:

x = [u'Rimegepant',u'Rimegepant',u'Zavegepant',u'Zavegepant',u'Troriluzole',u'Troriluzole',u'Troriluzole',u'Verdiperstat',u'Verdiperstat']
y = [4,3,3,3,2,3,3,3,3]

Disease = ['Acute Treatment of Migraine','Preventive Treatment of Migraine','Acute and Preventive Migraine','Lung Inflammation COVID-19',"Alzheimer's Disease", "OCD", "Spinocerebellar Ataxia", "Multiple System Atrophy", "Amyotrophic Lateral Sclerosis"]
Catalyst = ["Primary completion Oct 2021, Study completion Nov 2022",
            "Primary completion Oct 2021, Study completion Sept 20, 2022",
            "sdklfhslkijflk", "slkdjflskjf", "sikdjifliskj",
            "skdfhlskdhjfskldjflksjdflsk", "skidfhslikdjhfislkdjflskdfnlskdjflsk",
            "skdjfhlskdjlfksjdflksdjflskdjflskdjflskdjflksdjlkfnslkfnslkdfn",
            "Approved on Feb 27, 2020"]

fig = plt.figure(figsize=(12,5))
ax1 = fig.add_subplot()
ax2 = ax1.twinx()

width = 0.75 # the width of the bars
ind = np.arange(len(y))  # the x locations for the groups
ax1.barh(ind, y, width, color="green", align='edge')
ax1.set_yticks(ind+width/2)
ax1.set_yticklabels(x, minor=False)
ax1.set_ylabel('Drug')
ax1.set_xmargin(1.5)
ax1.autoscale_view()

ax2.set_ylim(ax1.get_ylim())
ax2.set_yticks(np.arange(len(Catalyst)) + width/2)
ax2.set_yticklabels(Catalyst,horizontalalignment = "right")
ax1.spines['right'].set_color('None')
ax2.spines['right'].set_color('None')

plt.xticks(np.arange(5),('Pre-clinical','Phase I','Phase II','Phase III', 'Approved'))

fig.suptitle('BHVN')
plt.show()

enter image description here

Upvotes: 1

Related Questions