i'm trying to create a table with below result in matplotlib , data extracted from MysQl.
i used theses charts inside An application built by PYQT5
but unfortunately this is what i get :
code used :
def dashboard_fleet_statistics_fleets_visisted_current_year(self):
try:
mydb = con.connect(host= "localhost", user ="root", password='''''', db="fleet")
cursor = mydb.cursor()
cursor.execute('''SELECT (fleet_code) ,fleet_name,COUNT(fleet_code) AS "No Of Visits",(Year(date_of_visit)) AS "Year Of Visit"
FROM vehicle_tyre_parameters
WHERE fleet_code != "" AND Year(date_of_visit)= Year(curdate())
GROUP BY fleet_code''')
result4 = cursor.fetchall()
print(list(result4))
fleet_code=[]
fleet_name=[]
no_of_visits =[]
fleet_year=[]
for row in result4 :
fleet_code.append(row[0])
fleet_name.append(row[1])
no_of_visits.append(row[2])
fleet_year.append(row[3])
print(list(fleet_code))
print(list(fleet_name))
print(list(no_of_visits))
print(list(fleet_year))
fig, ax = plt.subplots()
values=[fleet_code,fleet_name,no_of_visits,fleet_year]
table = ax.table(cellText=values,rowLabels=['Fleet Code','Fleet Name','No of Visits','Year of Visit'] ,colWidths=[.5,.5],colLoc='center',loc='center',bbox=[-0.3, 1, 1, 0.275])
#modify table
table.set_fontsize(14)
table.scale(1,4)
ax.axis('off')
table[(1, 0)].set_facecolor("white")
table[(2, 0)].set_facecolor("gray")
plt.tight_layout()
#display table
plt.show()
Appreciate your help to get a table with 1st picture ! Thanks
I cannot really access your data, but implementing the example you attached is pretty straightforward. I first put all the information in a pandas dataframe, and then used this neat trick that allows you to convert a dataframe to a matplotlib table. The rest is really playing with the design.
Here is a code snippet:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Create figure
fig, ax = plt.subplots(figsize = (25,2))
fig.patch.set_visible(False)
ax.axis('off')
ax.axis('tight')
# Make some data and put in dataframe
data = [['FC-1', 'NAME', 5, 2021], ['FC-6', 'NAME', 5, 2021]]
df = pd.DataFrame(data, columns=['Fleet code', 'Fleet name', 'Number of visits', 'Year of visit'])
# Create the table from the dataframe:
tab = ax.table(cellText=df.values, colLabels=df.columns, loc='center', cellLoc='center',
colColours = ['lightsteelblue', 'lightsteelblue', 'lightsteelblue', 'lightsteelblue'],
cellColours = [['w','w','w','w'], ['lightgray','lightgray','lightgray','lightgray']])
# Design the table:
# Fonts:
tab.auto_set_font_size(False)
tab.set_fontsize(20)
tab.scale(2, 2)
fig.tight_layout()
plt.show()
Here is the end result:
Related
I have printed a table that was in csv format using pandas library of python but I want to add title and some data in the bottom of the table before printing.
This my python code for printing table
I want my table to be printed like this with title: Table 5: Nauru Weighted Point System and at the bottom: State = 0 A = 8/Winner B = 5.82 C = 6.65
This example might lead you in the right direction..
import matplotlib.pyplot as plt
import pandas as pd
my_frame = pd.DataFrame(data={'Voters':['V1','V2','V3','V4'],
'True Preferece':['B>A>C','C>B>A','A>C>B','B>A>C'],
'Declared preference':['A>B>C','B>C>A','C>A>B','A>B>C'],
'Weights':[3,2,4,2]})
#my_frame Display pandas table
fig = plt.figure(figsize = (8, 2))
ax = fig.add_subplot(111)
ax.table(cellText = my_frame.values,
rowLabels = my_frame.index,
colLabels = my_frame.columns,
loc = "center"
)
ax.set_title("Table 5: Nauru Weigted Point system")
ax.axis("off");
This is link to the data I'm using:
https://github.com/fivethirtyeight/data/tree/master/drug-use-by-age
I'm using Jupyter Lab, and here's the code:
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sb
url = 'https://raw.githubusercontent.com/fivethirtyeight/data/master/drug-use-by-age/drug-use-by-age.csv'
df = pd.read_csv(url, index_col = 0)
df.dtypes
df.replace('-', np.nan, inplace=True)
df = df.iloc[:,:].astype(float)
df = df.loc[:, df.columns != 'n']
#df.columns = df.columns.str.rstrip('-use')
df
fig, axes = plt.subplots(1,2, figsize=(20, 8))
fig.subplots_adjust(wspace=0.1)
fig.colorbar(ax.collections[0], ax=ax,location="right", use_gridspec=False, pad=0.2)
#plt.figure(figsize=(16, 16))
df_percentage = df.iloc[:,range(0,26,2)]
plot_precentage = sb.heatmap(df_percentage, cmap='Reds', ax=axes[0], cbar_kws={'format': '%.0f%%', 'label': '% used in past 12 months'})
df_frequency = df.iloc[:,range(1,27,2)]
plot_frequency = sb.heatmap(df_frequency, cmap='Blues', ax=axes[1], cbar_kws= dict(label = 'median frequency a user used'))
I can just show two of them in a subplot in separate diagrams.
I want to make it look like this (this is made in paint):
Also show the data side by side. Is there a simple way to achieve that?
A pretty simple solution with mask option:
mask = np.vstack([np.arange(df.shape[1])]* df.shape[0]) % 2
fig, axes = plt.subplots()
plot_precentage = sns.heatmap(df,mask=mask, cmap='Reds', ax=axes,
cbar_kws={'format': '%.0f%%',
'label': '% used in past 12 months'}
)
plot_frequency = sns.heatmap(df, mask=1-mask, cmap='Blues', ax=axes,
cbar_kws= dict(label = 'median frequency a user used')
)
Output:
I have a pandas dataframe which I used the pandas.plot function to plot a bar chart. Within the function I set the table function to on. How can I format the values in this accompanying table with comma separators?
I am able to do these to the axis values, just not the accompanying table
I have already tried converting the values to float, but pandas plot only plots integers and therefore gives an error saying 'Empty Dataframe': no numeric data to plot.
ax1 = mydf.plot(kind='bar', title= chart with table, fontsize=8, width=0.75, legend=True, table=True)
ax1.legend(loc=5, bbox_to_anchor=(1.25,0.5), fontsize='x-small')
ax1.axes.get_xaxis().set_visible(False)
ax1.get_yaxis().get_major_formatter().set_scientific(False)
ax1.get_yaxis().set_major_formatter(ticker.StrMethodFormatter('${x:,.0f}'))
ax1.set_ylim(-10000000,10000000)
ax1.set_ylabel("P&L",fontsize=9)
ax1.axhline(0,0,1, color='k', linewidth=0.5)
table_ax1 = ax1.tables[0]
table_ax1.auto_set_font_size(False)
table_ax1.set_fontsize('8')
table_ax1.scale(1,2)
plt.tight_layout()
I don't know of a great way to force that formatting on the table ahead of time, without you explicitly making the matplotlib table yourself, however, you could iterate through the contents of the table and convert them this way instead (if you need to use the pandas implementation). I added some code in here from this related question demonstrating how the table can be manipulated as well.
import pandas as pd
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (5,5))
df= pd.DataFrame({'City': ['LA', 'SF', 'Dallas'],
'Lakes': [10000, 90000, 600000], # lets set some that can be comma formatted
'Rivers': [1, 0, 0],
'State': ['CA', 'CA', 'TX'],
'Waterfalls': [200500, 450000, 50000]})
myplot = df.plot(x=['City','State'],kind='bar',stacked='True',table=True, ax =ax)
### you can also scale and change the table
### see https://stackoverflow.com/questions/39668665/format-a-table-that-was-added-to-a-plot-using-pandas-dataframe-plot
myplot.axes.get_xaxis().set_visible(False)
# Getting the table created by pandas and matplotlib
table = myplot.tables[0]
# Setting the font size
table.set_fontsize(12)
# Rescaling the rows to be more readable
table.scale(1,2)
## to format the table values I will retrieve them and change them when they aren't text labels
xtls = ax.get_xticklabels()
xtls = [i.get_text() for i in xtls]
ax.set_xticklabels([])
t = ax.tables[0]
for c in t.get_children():
tobj = c.get_text()
text = tobj.get_text()
if text not in xtls:
try: # some texts will be strings that are labels, we can't convert them
s = '{:0,d}'.format(int(text))
tobj.set_text(s)
except:
pass
I am using Matplotlib's PdfPages to plot various figures and tables from queried data and generate a Pdf. I want to group plots by various sections such as "Stage 1", "Stage 2", and "Stage 3", by essentially creating section headers. For example, in a Jupyter notebook I can make cell's markdown and create bolded headers. However, I am not sure how to do something similar with PdfPages. One idea I had was to generate a 1 cell table containing the section title. Instead of creating a 1 cell table, it has a cell per character in the title.
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12, 2))
ax = plt.subplot(111)
ax.axis('off')
tab = ax.table(cellText=['Stage 1'], bbox=[0, 0, 1, 1])
tab.auto_set_font_size(False)
tab.set_fontsize(24)
This results in the following output:
If anyone has suggestions for how to create section headers or at least fix the cell issue in the table I created, I would appreciate your input. Thanks!
You need to use colLabels to name the columns and use the cellText with a corresponding shape
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12, 2))
ax = plt.subplot(111)
ax.axis('off')
length = 7
colLabels = ['Stage %s' %i for i in range(1,length+1)] # <--- 1 row, 7 columns
cellText = np.random.randint(0, 10, (1,length))
tab = ax.table(cellText=cellText, colLabels=colLabels, bbox=[0, 0, 1, 1], cellLoc = 'center')
tab.auto_set_font_size(False)
tab.set_fontsize(14)
Table with multiple rows
cellText = np.random.randint(0, 10, (3,length)) # <--- 3 rows, 7 columns
tab = ax.table(cellText=cellText, colLabels=colLabels, bbox=[0, 0, 1, 1], cellLoc = 'center')
To get a single row with multiple columns starting from 2 rows, 7 columns
tab = ax.table(cellText=[['']*length], colLabels=colLabels, bbox=[0, 0, 1, 1], cellLoc = 'center')
cells=tab.get_celld()
for i in range(length):
cells[(1,i)].set_height(0)
Getting a single column Using in the above code
length = 1
produces
A table expects two dimensional cellText. I.e. the mth column of the nth row has the content cellText[n][m]. If cellText=['Stage 1'], cellText[0][0] will evaluate to "S", because there is one row and the string inside is indexed as the columns. Instead you probably want to use
ax.table(cellText=[['Stage 1']])
i.e. the whole text as the first column of the first row.
Now the underlying question seems to be how to add a section title, and maybe using a table for that is not the best approach? At least a similar result could be achieved with a usual text,
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 2))
ax.tick_params(labelleft=False, left=False, labelbottom=False, bottom=False)
ax.annotate('Stage 1', (.5,.5), ha="center", va="center", fontsize=24)
plt.show()
I may be misunderstanding your question, but if your ultimate goal is to group multiple plots together in PDF, one solution is to make each of your plots a subplot of the same figure. For example:
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
import random
# Declare the PDF file and the single figure
pp = PdfPages('test.pdf')
thefig = plt.figure()
thefig.suptitle("Group 1")
# Generate 4 subplots for the same figure, arranged in a 2x2 grid
subplots = [ ["Plot One", 221], ["Plot Two", 222],
["Plot Three", 223], ["Plot Four", 224] ]
for [subplot_title, grid_position] in subplots:
plt.subplot(grid_position)
plt.title(subplot_title)
# Make a random bar graph:
plt.bar(range(1,11), [ random.random() for i in range(10) ])
# Add some spacing, so that the writing doesn't overlap
plt.subplots_adjust(hspace=0.35, wspace=0.35)
# Finish
pp.savefig()
pp.close()
When I do this, I get something like the following:
Hi, I am plotting a Pandas dataframe. The Pandas Dataframe look like this:
;Cosine;Neutralized
author;0.842075;0.641600
genre;0.839696;0.903227
author+genre;0.833966;0.681121
And the code for plotting that I am using is:
fig = ari_total.plot(kind="bar", legend = False, colormap= "summer",
figsize= ([7,6]), title = "Homogeinity "+corpora+" (texts: "+str(amount_texts)+")", table=True,
use_index=False, ylim =[0,1]).get_figure()
The result is nice, but it has a problem:
As you can see, the labs from the index of the table "author", "genre" and "author+gender" are render over 0, 1 and 2.
My question: how can I delete this numbers and still using the same function? I am using the argument use_index=False, which I thought they would delete the labels from the bars, but it actually only replace them with this numbers...
I would be very thankfull if you could help. Regards!
Use fig.axes[0].get_xaxis().set_visible(False).
code:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame()
df['Cosine'] = [0.842075,0.839696,0.833966]
df['Neutralized'] = [0.641600,0.903227,0.681121]
df.index = ['author', 'genre', 'author+genre']
fig = df.plot(kind="bar", legend = False, colormap= "summer",
figsize= ([7,6]), title = "whatever", table=True,
use_index=False, ylim =[0,1]).get_figure()
fig.axes[0].get_xaxis().set_visible(False)
plt.show()
result: