Using pptx without having to first save outputs to jpg files - python

I am creating a powerpoint in Python, where the slides are the output graphs from the Jupyter Notebook cells.
I am able to do this, but only if I save each output as a jpg. For example, see the code below:
data = pd.read_csv("123.csv")
data.columns = ['Color Group', 'BASE VOLUME']
x= data['BASE VOLUME']
y= data['Color Group']
data2 = data
data2['BASE VOLUME %'] = data2['BASE VOLUME']
data2 = data2.iloc[:,[0,2]]
data2['BASE VOLUME %'] = 100*data2['BASE VOLUME %']/(sum(data2['BASE VOLUME %']))
data2['Type'] = 'Total'
total = data2.copy()
plt.figure(figsize=(10,6))
clrs = ['deepskyblue' if (x > 10) else 'gray' for x in data2['BASE VOLUME %']]
ax = sns.barplot(x,y, data=data2, palette=clrs)
ax.set_xlabel('Base Volume',fontsize=15)
ax.set_ylabel('Color Group',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
for i, v in enumerate(data2['BASE VOLUME %']):
ax.text(0 + 0.01*max(data['BASE VOLUME']), i + len(data2)/50, str("{0:.1f}%".format(v)), color='black', fontweight='bold', fontsize=14)
plt.title('Total'.format(s),fontsize=15)
plt.savefig("Total.jpg",bbox_inches='tight')
#Create Powerpoint
from pptx import Presentation
from pptx.util import Inches,Pt
prs = Presentation('input.pptx')
blank_slide_layout = prs.slide_layouts[1]
img1 = 'Total.jpg'
slide = prs.slides.add_slide(blank_slide_layout)
pic = slide.shapes.add_picture(img1, Inches(0.55), Inches(2), height=Inches(4.8), width=Inches(8.8))
title = slide.shapes.title
title.text_frame.paragraphs[0].font.size=Pt(50)
title.text = "Total"
Is there a way of creating a similar line toplt.savefig("Total.jpg",bbox_inches='tight'), without saving a file - i.e calling the plot "something (say x)" that can be called back at any point? Then later I can replace the line img1 = 'Total.jpg' with img1 = x etc.

Related

Add new sheet with graph

newby question.
I would like to add a new sheet to an existing wb that I've created with xlwings.
It seems that when I try to add e write the 2nd sheet the 1st one going to be overwritten.
Here the code :
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns # library for visualization
sns.set() # this command sets the seaborn chart style as the default
import xlwings as xw
from datetime import datetime
df=pd.read_excel('aspire_1909.xls')
df2=df.drop([0,2])
new_header = df2.iloc[1]
df2 = df2[2:]
df2.columns = new_header
df2=df2.set_index('User')
wb = xw.Book()
sht = wb.sheets[0]
sht.name = "Aspire Manager Graph"
sht.range('R1').value = df3
started=len(df3.loc[df3['Manager Review'] == 'Started'])
complete = len(df3.loc[df3['Manager Review'] == 'Complete'])
complete_reopened = len(df3.loc[df3['Manager Review'] == 'Complete (Reopened)'])
not_started = len(df3.loc[df3['Manager Review'] == 'Not Started'])
past_due = len(df3.loc[df3['Manager Review'] == 'Past Due'])
def insert_heading(rng,text):
rng.value = text
rng.font.bold = True
rng.font.size = 24
rng.font.color = (0,0,139)
insert_heading(sht.range("A2"),f"ASPIRE YEAR END REVIEW - MANAGER STATUS del {datetime.today().strftime('%d-%m-%Y')}")
data = {'Not Started':not_started, 'Started':started, 'Completed':complete,'Reopened' : complete_reopened,'Past Due ' : past_due }
status = list(data.keys())
values = list(data.values())
x_labels = list(a + ' ' + str(b) for (a, b) in zip(status, values))
fig = plt.figure(figsize = (10, 5))
# creating the bar plot
fig, ax = plt.subplots(figsize=(15, 15))
bars = ax.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
ax.bar_label(bars, fmt="%d", fontsize=26, rotation=0, padding=3)
plt.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
plt.xticks(status, x_labels)
plt.xticks(rotation = 45, fontsize = 13)
plt.xlabel("Year End Review Completion Status")
plt.ylabel("No Users",rotation=45,fontsize = 13)
plt.title("Aspire Mgr Year End Review")
plt.show()
sht.pictures.add(fig,
name = "Aspire Mgr Status Graph",
update = True,
left =sht.range("A4").left,
top = sht.range("A4").top,
height= 500,
width= 700)
sht1 = wb.sheets[0]
wb.sheets.add('Aspire Employees Graph')
sht1.range('R1').value = df2
started=len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Started'])
complete = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Complete'])
complete_reopened = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Complete (Reopened)'])
not_started = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Not Started'])
past_due = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Past Due'])
def insert_heading(rng,text):
rng.value = text
rng.font.bold = True
rng.font.size = 24
rng.font.color = (0,0,139)
insert_heading(sht1.range("A2"),f"ASPIRE YEAR END REVIEW EMPLOYEE STATUS del {datetime.today().strftime('%d-%m-%Y')}")
data = {'Not Started':not_started, 'Started':started, 'Completed':complete,'Reopened' : complete_reopened,'Past Due ' : past_due }
status = list(data.keys())
values = list(data.values())
x_labels = list(a + ' ' + str(b) for (a, b) in zip(status, values))
fig = plt.figure(figsize = (10, 5))
# creating the bar plot
fig, ax = plt.subplots(figsize=(15, 15))
bars = ax.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
ax.bar_label(bars, fmt="%d", fontsize=26, rotation=0, padding=3)
plt.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
plt.xticks(status, x_labels)
plt.xticks(rotation = 45, fontsize = 13)
plt.xlabel("Year End Review Completion Status")
plt.ylabel("Nb. Users",rotation=45,fontsize = 13)
plt.title("Aspire Employee Year End Review")
plt.show()
sht1.pictures.add(fig,
name = "Aspire Employee Status Graph",
update = True,
left =sht.range("A4").left,
top = sht.range("A4").top,
height= 500,
width= 700)
Could someone would be able to help me get what Is wrong ? ( I know ,almost everything :-) )
Thanks a lot in advance
In the second half of the code you have:
sht1 = wb.sheets[0]
wb.sheets.add('Aspire Employees Graph')
sht1.range('R1').value = df2
What wb.sheets[0] is returning is the very first sheet of the workbook. Towards the beginning you have the first section, which is:
sht = wb.sheets[0]
sht.name = "Aspire Manager Graph"
sht.range('R1').value = df3
As you use wb.sheets[0] both times, but haven't inserted a sheet at the beginning, you are just referring to the same sheet. The addition of the new sheet is correct, but you haven't set that as variable sht1.
Instead, for the second section, you could re-write to the following, combining the two lines into one so that the variable is the correct sheet:
sht1 = wb.sheets.add('Aspire Employees Graph')
sht1.range('R1').value = df2
Edit
To change the colour of the sheet tab:
sht1.api.Tab.ColorIndex = 3
The full list of colours can be found in the VBA ColorIndex documentation.
For more specific colours, see the answers to this question.

Creating a legend, and printing a graph with python

I am wanting to add a legend to the graph below and download it as a pdf. The code I have for the graph is below.
%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
mta = pd.read_csv('../project/all_mta_data_cleanded.csv') # mta data cleanded into similare catagories
cata = pd.read_csv('../project/mta_catagories_breakdown.csv') #document combining all of the catagories
weather = pd.read_csv('../project/New York Tempeture Data.csv')
mta['Total Lost Items'] = mta['Total Lost Items'] = (mta['Accessories']+ mta['Books'] + mta['Bags'] + mta['Cellphones'] + mta['Clothing'] + mta['Money'] + mta['Eletronics'] + mta['Entrainment'] + mta['Glasses'] + mta['Shoes'] + mta['Household Items'] + mta['Indentification'] + mta['Jewlery'] + mta['Keys'] + mta['Medical Equipment'] + mta['Miscellaneous'] + mta['Instruments'] + mta['NYCT Equipment'] + mta['Sports Equipment'] + mta['Tickets'] + mta['Tools'] + mta['Toys'] + mta['Wallets/Purses'])
clear = mta.iloc[[13, 40,68,92,115,138,157,176,200,222,241,245,246,250],:] #selected the last pull of each month
compl = pd.merge(clear,weather, left_on='Date',right_on='Time',how='outer').drop(columns=['Time'])
fig, ax1 = plt.subplots()
ax1.plot(compl['Date'], compl['Temp'] ,color = 'red',marker='o')
ax2= ax1.twinx()
ax2.plot(compl['Date'], compl['Total Lost Items'],color= 'purple',marker='^')
ax1.set_ylabel('Tempeture in Fahrenheit', )
for tick in ax1.get_xticklabels():
tick.set_rotation(90)
ax2.set_ylabel('Number Of Items Lost')
ax1.set_title('Average Weather In New Your City vs Total Items Lost Each Month')
plt.set_legend()
plt.figure.savefig('Project Figure.pdf')```
to add a legend to your graph you have to specify the field "label" in plt.plot(), use plt.legend() and plt.show()
fig, ax1 = plt.subplots()
l1 = ax1.plot(compl['Date'], compl['Temp'] ,color = 'red',marker='o', label = 'label_1')
ax2= ax1.twinx()
l2 = ax2.plot(compl['Date'], compl['Total Lost Items'],color= 'purple',marker='^', label = 'label_2')
ax1.set_ylabel('Temperature in Fahrenheit')
for tick in ax1.get_xticklabels():
tick.set_rotation(90)
ax2.set_ylabel('Number Of Items Lost')
ax1.set_title('Average Weather In New Your City vs Total Items Lost Each Month')
plt.legend([l1,l2],['lab1', 'lab2'])
plt.show()
plt.savefig('Project Figure.pdf')

How to get updated bokeh graph in streamlit (server issue?)

I want to embed a bokeh graphic in streamlit. the interactive bokeh graph is operational with the command boker serve --show application.
But when I integrate it into streamlit, I have the graph that appears but the updates with the tabs are broken.
Is there a possibility to run everything on streamlit, without going through a bokeh server?
Here is my code
import pandas as pd
from bokeh.layouts import column, row
from bokeh.models import Select
from bokeh.palettes import Spectral5
from bokeh.plotting import curdoc, figure, show
df = pd.read_csv(r'C:\mypath\myfile.csv')
SIZES = list(range(6, 22, 3))
COLORS = Spectral5
N_SIZES = len(SIZES)
N_COLORS = len(COLORS)
columns = sorted(df.columns)
discrete = [x for x in columns if df[x].dtype == object]
continuous = [x for x in columns if x not in discrete]
def create_figure():
xs = df[x.value].values
ys = df[y.value].values
x_title = x.value.title()
y_title = y.value.title()
kw = dict()
if x.value in discrete:
kw['x_range'] = sorted(set(xs))
if y.value in discrete:
kw['y_range'] = sorted(set(ys))
kw['title'] = "%s vs %s" % (x_title, y_title)
p = figure(height=600, width=800, tools='pan,box_zoom,hover,reset', **kw)
p.xaxis.axis_label = x_title
p.yaxis.axis_label = y_title
if x.value in discrete:
p.xaxis.major_label_orientation = pd.np.pi / 4
sz = 9
if size.value != 'None':
if len(set(df[size.value])) > N_SIZES:
groups = pd.qcut(df[size.value].values, N_SIZES, duplicates='drop')
else:
groups = pd.Categorical(df[size.value])
sz = [SIZES[xx] for xx in groups.codes]
c = "#31AADE"
if color.value != 'None':
if len(set(df[color.value])) > N_COLORS:
groups = pd.qcut(df[color.value].values, N_COLORS, duplicates='drop')
else:
groups = pd.Categorical(df[color.value])
c = [COLORS[xx] for xx in groups.codes]
p.circle(x=xs, y=ys, color=c, size=sz, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)
return p
def update(attr, old, new):
layout.children[1] = create_figure()
x = Select(title='X-Axis', value='Distance (m)', options=columns)
x.on_change('value', update)
y = Select(title='Y-Axis', value='Jumps', options=columns)
y.on_change('value', update)
size = Select(title='Size', value='None', options=['None'] + continuous)
size.on_change('value', update)
color = Select(title='Color', value='None', options=['None'] + continuous)
color.on_change('value', update)
controls = column(x, y, color, size, width=200)
layout = row(controls, create_figure())
curdoc().add_root(layout)
curdoc().title = "AppAnalyse"
st.bokeh_chart(layout, use_container_width=True)
when I run this code on streamlit, I have the graph on streamlit but the updates do not work (see photo1)
streamlit graph ok but no update
then when I execute the command: boker serve --show application, from the console, I get the desired graph on a server, which is functional (see photo 2)
graph ok on bokeh serve
there is a possibility to integrate this graph with "st.bokeh_chart()" to get this graph in streamlit with functional updates?
Thank you very much for the help provided and excuse my English please :)

The file gives an error when I add label position to python pptx doughnut chart

I try to add labels for a doughnut chart. Everything works fine until I try to set the position of labels. Neither BEST_FIT nor OUTSIDE_END work. When I add data_labels.position = XL_LABEL_POSITION.BEST_FIT line the file just won't open. Here is the code:
from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LABEL_POSITION
from pptx.util import Inches, Pt
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6]) # blank slide
chart_data = ChartData()
chart_data.categories = ['aaa','bbb', 'ccc','ddd', 'eee', 'fff','ggg','hhh', 'iii', 'jjj','kkk','lll','mmm', 'nnn']
chart_data.add_series('Test', [10,50,60,30,5,35,10,15,70,1,10,5,60,30])
x, y, cx, cy = Inches(1), Inches(1), Inches(8), Inches(6)
chart = slide.shapes.add_chart(XL_CHART_TYPE.DOUGHNUT, x, y, cx, cy, chart_data).chart
chart.plots[0].has_data_labels=True
data_labels = chart.plots[0].data_labels
data_labels.font.size = Pt(12)
data_labels.show_percentage = True
data_labels.show_category_name = True
data_labels.show_value = True
data_labels.position = XL_LABEL_POSITION.BEST_FIT
#or
#data_labels.position = XL_LABEL_POSITION.OUTSIDE_END
prs.save('test.pptx')
As you can imagine, my real data category names are much longer and without proper positioning it is impossible to read. So how can I set the position of labels so that they are readable?

Multiple Sns plot distort in flask using savefig and sendfile

I have a html file that displays the images sent from the flask backend.
<body>
<h3> Count plot of data according to Lead origin.</h3>
<img src = "/graph_visualization/" alt = "graph it is" height = "300" width = "300">
<h3> Count plot of data according to cities</h3>
<img src = "/graph_visualization2/" alt = "graph it is" height = "300" width = "300">
<h3> Count plot of data according to Countries</h3>
<img src = "/graph_visualization3/" alt = "graph it is" height = "300" width = "300">
</body>
The three plots are sent as a png file from multiple functions in flask backend as below:
#app.route('/graph_visualization/')
def graph_visualization():
fig, ax = plt.subplots()
df = pd.read_csv(r'C:\Users\Admin\Downloads\export.csv')
sns.countplot(x="Lead Origin", hue="Converted", data=df)
canvas = FigureCanvas(fig)
img = BytesIO()
fig.savefig(img, format='png')
img.seek(0)
return send_file(img, mimetype='image/png', cache_timeout=-1)
#app.route('/graph_visualization2/')
def graph_visualization2():
fig1, ax = plt.subplots()
df = pd.read_csv(r'C:\Users\Admin\Downloads\export.csv')
sns.countplot(x="Cities", hue="Converted", data=df)
xticks(rotation=90)
plt.tight_layout()
canvas = FigureCanvas(fig1)
img1 = BytesIO()
fig1.savefig(img1, format='png')
img1.seek(0)
return send_file(img1, mimetype='image/png', cache_timeout=-1)
#app.route('/graph_visualization3/')
def graph_visualization3():
fig2, ax = plt.subplots()
df = pd.read_csv(r'C:\Users\Admin\Downloads\export.csv')
sns.barplot(x="Countries", y="Converted", data=df)
xticks(rotation=90)
plt.tight_layout()
plt.ylabel('Converted')
plt.xlabel('Countries')
canvas = FigureCanvas(fig2)
img2 = BytesIO()
fig2.savefig(img2, formar='png')
img2.seek(0)
return send_file(img2, mimetype='image/png', cache_timeout=-1)
Note: Individual graph shows when i comment any two functions and only keep one. The problem is when i uncomment all of them.
I have tried following methods:
Changing the figurename and image name in each functions.
plt.clf() below fig.savefig()
ax.clear() below fig, ax = plt.subplots()
Run in Incognito mode.
Note: I don't want to make multiple subplots.
Please let me know if my approach to the problem is incorrect.

Categories