Semi circle donut chart python-pptx - python

Is there a way to create a semi circle donut chart using the pptx library in python?
I couldn't really find any information
Thanks

I would do something as below. First I would create a semi pie chart in matplotlib and then I would save it. After saving it I would add it to the presentation.
import matplotlib.pyplot as plt
import numpy as np
from pptx import Presentation
from pptx.util import Inches
data = [20, 30, 50]
fig, ax = plt.subplots()
ax.pie(data, startangle=90, radius=1, counterclock=False, wedgeprops=dict(width=0.3))
plt.savefig("semi_circle_donut.png")
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6])
left = top = Inches(1)
pic = slide.shapes.add_picture(
"semi_circle_donut.png", left, top, height=Inches(5), width=Inches(5)
)
prs.save("semi_circle_donut.pptx")

Related

how can I add two different images to my code?

I'm trying to add two different images (png) to my code and The result shows me the same image twice,I tried to add the different image to the same code but it showed me an error, I tried to change the names of the function but did not giveת I tried to download the image under a different name, how can I solve it?
this is my code :
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.chart.data import ChartData
import matplotlib.pyplot as plt
import pandas as pd
import sys
from SQLConnector import SQLConnector
import seaborn as sns
from pptx.util import Inches
from PIL import Image
def px_to_inches(path):
im = Image.open(path)
width = im.width / im.info['dpi'][0]
height = im.height / im.info['dpi'][1]
return (width, height)
def sick_percentage():
bi_sql = SQLConnector(db='bi')
sql_query = "<some query>"
data_from_bi = bi_sql.query_by_str(sql_query)
return data_from_bi
df = sick_percentage()
prs = Presentation()
# create presentation with 1 slide ------
slide = prs.slides.add_slide(prs.slide_layouts[5])
# define chart data ---------------------
title = slide.shapes.title
title.text = "<title>"
# define chart data ---------------------
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
df.plot(x='date', y='positives', kind='bar', color='orange', ax=ax1)
df['percent_positive'].plot(x='date', kind='line', marker='d', ax=ax2)
ax1.yaxis.tick_right()
ax2.yaxis.tick_left()
plt.savefig('graph.png')
img = px_to_inches('graph.png')
slide_size = (16, 9)
left = Inches(slide_size[0] - img[0]) / 5.5
top = Inches(slide_size[1] - img[1]) / 2
pic = slide.shapes.add_picture('graph.png', left, top)
img = px_to_inches('pkar.png')
slide_size = (4,5)
left = Inches(slide_size[0] - img[0]) / 10
top = Inches(slide_size[1] - img[1]) / 2
pic = slide.shapes.add_picture('pkar.png', left, top)
prs.save('chart-01.pptx')
I don't know exactly how these modules work, but I think your problem is due to setting img and pic to the two different images.
I would guess that the presentation isn't saved until you call prs.save, and at that point it renders all of the slides. When this is called, img and pic both refer to pkar.png.
It might be a better practice to always name the pic/img based on the slide number, ie first slide has img1 and pic1, second slide has img2 and pic2, etc. Better yet, give them informative names, like "img_graph" and "pic_graph", or even better "img_pi_graph_users", etc. That way you aren't overwriting variables, and if you end up with much longer code, the variables are named in a way that you don't have to look back to what you set them to previously.

Seaborn or Matplotlib Boxplot with rounded corners

I'd like to do a boxplot with rounded corners but not sure how. Saw a post to make rounded corners for barplot but no luck with boxplot. ax.artists is a list of matplotlib.patches.PathPatch objects and I think they control the box styles.
Below is some sample code
import pandas as pd
import numpy as np
import seaborn as sns
df = pd.DataFrame(np.random.rand(100, 1), columns=['value'])
df['type'] = pd.Series(np.repeat(['type1','type2', 'type3', 'type4'], 25))
ax = sns.boxplot(data=df, x="type", y="value")
There are similar questions (e.g. Bar chart with rounded corners and Seaborn barplot with rounded corners). These solutions need quite some adaptions to be usable here.
The boxplot's rectangles aren't stored as rectangles, but as patch artists. To get their bounding box, the entent of their path needs to be calculated.
The parameters of FancyBboxPatch need some experimenting. Setting pad=0 makes the rounded rectangle occupy the same space. mutation_aspect (defaults to 1) is needed to make the vertical boxes look well. For your own application, some fine-tuning might be needed.
from matplotlib import pyplot as plt
from matplotlib.patches import FancyBboxPatch
from matplotlib.path import get_path_collection_extents
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(100, 1), columns=['value'])
df['type'] = pd.Series(np.repeat(['type1', 'type2', 'type3', 'type4'], 25))
ax = sns.boxplot(data=df, x="type", y="value")
new_patches = []
for patch in reversed(ax.artists):
bb = patch.get_path().get_extents()
color = patch.get_facecolor()
p_bbox = FancyBboxPatch((bb.xmin, bb.ymin),
abs(bb.width), abs(bb.height),
boxstyle="round,pad=0,rounding_size=0.2",
ec="black", fc=color,
mutation_aspect=0.2)
patch.remove()
new_patches.append(p_bbox)
for patch in new_patches:
ax.add_patch(patch)
plt.show()

Adjusting size of matplot lib figure (including title and tick labels)- hidden when sizing down figure

I'm creating an html page with a dropdown menu. When the user hits the "submit" button after making their selection from the dropdown menu, the cgi script runs and pulls data from a csv file, plots it using matplotlib, and then displays the plot using base64. The plot has dates along the x-axis and percentage on the y-axis.
I've got it all working in python 3.8 using spyder, but when I load it to my server (which uses python 3.4) it creates a huge plot that I have to scroll on the browser. When I change the figsize to height less than 10, it cuts off the x-axis label and tick labels. I've rotated the xticks 30* to make them readable. How do I essentially "zoom out" on the entire figure including tick & axis labels?
Here's the portion of my code that creates the plot:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import base64
fig, ax = plt.subplots(figsize=(15, 10))
df = pd.read_csv(filepath, header=1, parse_dates=['Report_Date'], index_col=['Report_Date'])
ax.plot(df.index.values, df['colname'], color='teal')
ax.yaxis.set_major_formatter(mtick.PercentFormatter(xmax=1, decimals=None, symbol='%', is_latex=False))
plt.xlabel('Report Date')
plt.ylabel('ylabel')
plt.title('title')
plt.xticks(rotation=30, ha='right')
plt.savefig('picture.png', dpi=200)
data_uri = base64.b64encode(open('picture.png','rb').read()).decode('utf-8')
img_tag = '<img src='data:image/png;base64,{0}>'.format(data_uri)
print(img_tag)
I think that the simplest way for you is to add
plt.tight_layout before plt.savefig
like this:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import base64
fig, ax = plt.subplots(figsize=(15, 10))
df = pd.read_csv(filepath, header=1, parse_dates=['Report_Date'], index_col=['Report_Date'])
ax.plot(df.index.values, df['colname'], color='teal')
ax.yaxis.set_major_formatter(mtick.PercentFormatter(xmax=1, decimals=None, symbol='%', is_latex=False))
plt.xlabel('Report Date')
plt.ylabel('ylabel')
plt.title('title')
plt.xticks(rotation=30, ha='right')
plt.tight_layout()
plt.savefig('picture.png', dpi=200)
data_uri = base64.b64encode(open('picture.png','rb').read()).decode('utf-8')
img_tag = '<img src='data:image/png;base64,{0}>'.format(data_uri)
print(img_tag)
more info about it : https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.tight_layout.html

Setting Image background for a line plot in matplotlib

I am trying to set a background image to a line plot that I have done in matplotlib. While importing the image and using zorder argument also, I am getting two seperate images, in place of a single combined image. Please suggest me a way out. My code is --
import quandl
import pandas as pd
import sys, os
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import itertools
def flip(items, ncol):
return itertools.chain(*[items[i::ncol] for i in range(ncol)])
df = pd.read_pickle('neer.pickle')
rows = list(df.index)
countries = ['USA','CHN','JPN','DEU','GBR','FRA','IND','ITA','BRA','CAN','RUS']
x = range(len(rows))
df = df.pct_change()
fig, ax = plt.subplots(1)
for country in countries:
ax.plot(x, df[country], label=country)
plt.xticks(x, rows, size='small', rotation=75)
#legend = ax.legend(loc='upper left', shadow=True)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show(1)
plt.figure(2)
im = plt.imread('world.png')
ax1 = plt.imshow(im, zorder=1)
ax1 = df.iloc[:,:].plot(zorder=2)
handles, labels = ax1.get_legend_handles_labels()
plt.legend(flip(handles, 2), flip(labels, 2), loc=9, ncol=12)
plt.show()
So in the figure(2) I am facing problem and getting two separate plots
In order to overlay background image over plot, we need imshow and extent parameter from matplotlib.
Here is an condensed version of your code. Didn't have time to clean up much.
First a sample data is created for 11 countries as listed in your code. It is then pickled and saved to a file (since there is no pickle file data).
import quandl
import pandas as pd
import sys, os
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import itertools
from scipy.misc import imread
countries = ['USA','CHN','JPN','DEU','GBR','FRA','IND','ITA','BRA','CAN','RUS']
df_sample = pd.DataFrame(np.random.randn(10, 11), columns=list(countries))
df_sample.to_pickle('c:\\temp\\neer.pickle')
Next the pickle file is read and we create bar plot directly from pandas
df = pd.read_pickle('c:\\temp\\neer.pickle')
my_plot = df.plot(kind='bar',stacked=True,title="Plot Over Image")
my_plot.set_xlabel("countries")
my_plot.set_ylabel("some_number")
Next we use imread to read image into plot.
img = imread("c:\\temp\\world.png")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.imshow(img,zorder=0, extent=[0.1, 10.0, -10.0, 10.0])
plt.show()
Here is an output plot with image as background.
As stated this is crude and can be improved further.
You're creating two separate figures in your code. The first one with fig, ax = plt.subplots(1) and the second with plt.figure(2)
If you delete that second figure, you should be getting closer to your goal

changing major/minor axis interval and color scheme for heatmap

You can find my data set here.
I am using seaborn to plot the heatmap. But open to other choices.
I have trouble getting the color scheme right. I wish to have a black and white scheme. As the current color scheme doesn't clear show the result.
I also wish to display only x and y intervals as (0 , 25 , 50, 100 , 127).
How can I do this.
Below is my try:
import pandas as pd
import numpy
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
data_sorted = pd.read_csv("tors_sorted.txt", sep="\t")
ax = plt.axes()
ax.set_xlim(right=128)
minor_ticks = numpy.arange(0, 128, 50) # doesn't seem to work
data_sorted= data_sorted.pivot("dst","src","pdf_num_bytes")
#sns.heatmap(data_sorted,ax=ax)
sns.heatmap(data_sorted,linecolor='black',xticklabels=True,yticklabels=True)
ax.set_title('Sample plot')
ax.set_xticks(minor_ticks, minor=True)
fig = ax.get_figure()
fig.savefig('heatmap.jpg')
This is the image that I get.
thanks.

Categories