I'm trying to create a bar chart with multiple bars in Python. The bar chart should display values on top of each bar.
I have a data set like the following:
Speciality Very interested Somewhat_interested Notinterested
Big Data (Spark/Hadoop) 1332 729 127
Data Analysis / Statistics 1688 444 60
Data Journalism 429 1081 610
I have tried the following code:
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
pd_dataframe = pd.read_csv('Test-Barchart.csv')
no_of_xaxis = pd_dataframe.Speciality.nunique()
ind = np.arange(no_of_xaxis)
xcord = pd_dataframe['Speciality'].tolist()
veryinterestedlist = pd_dataframe['Very interested'].tolist()
somewhatlist = pd_dataframe['Somewhat interested'].tolist()
notinterestedlist = pd_dataframe['Not interested'].tolist()
fig=plt.figure()
ax = fig.add_subplot(111)
width=0.8
rects1 = ax.bar(ind, veryinterestedlist, width, color='r')
rects2 = ax.bar(ind, somewhatlist, width, color='g')
rects3 = ax.bar(ind+width*2, notinterestedlist, width, color='b')
ax.legend( (rects1[0], rects2[0], rects3[0]), ('Very Interested',
'Somewhat Interested', 'Not Interested') )
def autolabel(rects):
for rect in rects:
h = rect.get_height()
ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, '%d'%int(h),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
ax.set_xticks(ind+width)
ax.set_xticklabels( xcord )
plt.show()
The problem is, plt.show() is not showing anything!
I don't have any errors in the code.
Could you please help me resolve this problem?
Also how can i change bar color to hex code color instead of r,g or b? e.g. #5bc0de
Small changes to your code:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
pd_dataframe = pd.read_csv('Test-Barchart.csv')
no_of_xaxis = pd_dataframe.Speciality.nunique()
ind = np.arange(no_of_xaxis)
width = 0.1
xcord = pd_dataframe['Speciality'].tolist()
veryinterestedlist = pd_dataframe['Very interested'].tolist()
somewhatlist = pd_dataframe['Somewhat interested'].tolist()
notinterestedlist = pd_dataframe['Not interested'].tolist()
fig, ax = plt.subplots()
rects1 = ax.bar(ind, veryinterestedlist, width, color='g')
rects2 = ax.bar(ind + width, somewhatlist, width, color='c')
rects3 = ax.bar(ind+2*width, notinterestedlist, width, color='r')
# add some text for labels, title and axes ticks
ax.set_ylabel('y label')
ax.set_title('Title')
ax.set_xticks(ind + width)
ax.set_xticklabels(xcord)
ax.legend( (rects1[0], rects2[0], rects3[0]), ('Very Interested',
'Somewhat Interested', 'Not Interested') )
def autolabel(rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
plt.show()
and you get:
Reference: Grouped bar chart with labels
Related
I'm trying to create the following plot in python:
Unfortunatelly, the positioning of the text seems to be very erratic, as when I try to move the text in the right panel to the right I get the following plot:
The code I am using the generate the plot is the following:
fig, ax = plt.subplots(figsize = (12,6), constrained_layout=True)
gs = fig.add_gridspec(1, 2, left=0.05, right=0.5, wspace=0.01)
plt.rcParams.update({'font.size': 12})
# plt.set_cmap('OrRd') # https://matplotlib.org/stable/tutorials/colors/colormaps.html
plt.set_cmap('binary')
ax.axis('off')
xmax = 20
color = 'red'
# Left plot
ax1 = fig.add_subplot(gs[0,0])
ax1.set_xlim([-0.5, xmax])
ax1.hist(data, bins = 11, density = True, color = color)
ax1.axes.get_yaxis().set_ticks([])
ax1.set_xlabel("S(m{}|m{})".format(D1,D2))
plt.gca().invert_xaxis()
# right plot
ax2 = fig.add_subplot(gs[0,1])
ax2.set_xlim([-0.5, xmax])
ax2.hist(data, bins = 14, density = True, color = color)
ax2.set_xlabel("S(m{}|m{})".format(D2,D1))
ax2.axes.get_yaxis().set_visible(False)
# legenda
textstr12 = '\n'.join((
"S(m{}|m{}) = {:.2f}".format(D1,D2, S12),
"D(m{}|m{}) = {:.2f}".format(D1,D2, D12),
"<D> = {:.2f}".format(exp_D12)))
textstr21 = '\n'.join((
"S(m{}|m{}) = {:.2f}".format(D2,D1, S21),
"D(m{}|m{}) = {:.2f}".format(D2,D1, D21),
"<D> = {:.2f}".format(exp_D21)))
# generate text
props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
ax1.text(0.05, 0.95, textstr21, transform=ax.transAxes, fontsize=14, verticalalignment='top', bbox=props) #aqui irá mostrar a caixa na esquerda! por isso inverto para o caso S21.
################### line bellow is the buggy part
##### if I set ax2.text(0.57, 0.95, ...) I get the correct figure
ax2.text(0.97, 0.95, textstr12, transform=ax.transAxes, fontsize=14, verticalalignment='top', bbox=props)
plt.show()
I finally managed to make my animations work. The only problem comes when I save them with ffmpeg writer. A ~250 frame gif takes literally a few hours to save. It took me 3 hours to save an 11 second video.
What is making it take so long??
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import contextily as cx
from matplotlib.offsetbox import AnchoredText
#Writer information, path, and where to save
plt.rcParams['animation.ffmpeg_path'] =r"the path I saved ffmpeg"
#writer = animation.writers['ffmpeg']
f = r"location I will save the .mp4"
# Reads the Excel sheet specified from the doc. IT ONLY OPENS .XLSM
df = pd.read_excel(r'the excel file', sheet_name='the sheet name')
# Creates a list of important datasets
df['Points'] = list(zip(df.Latitude,df.Longitude))
Longs = list(df.Longitude)
Lats = list(df.Latitude)
Time = list(df.Last_Record)
Speed = list(df.Speed)
#This is the list of Coordinates
Coords = df['Points']
#print(Coords)
#how many frames to save for the animation
savecount = len(Longs)
print("Frames: ",savecount)
#turns the dataframe into a geodataframe
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.Longitude, df.Latitude),crs='EPSG:4326')
#Geodataframe boundaries
minx, miny, maxx, maxy = gdf.geometry.total_bounds
print("Boundaries: ",minx, miny, maxx, maxy)
#plt background
ax = gdf.plot(figsize=(6,6), alpha =0.5, facecolor="None")
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0,
hspace = 0, wspace = 0)
ax.margins(0,0)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.axis('off')
#North arrow
x, y, arrow_length = 0.85, 0.10, 0.07
ax.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=5, headwidth=15),
ha='center', va='center', fontsize=20,
xycoords=ax.transAxes)
#Use contextily to create the basemap
cx.add_basemap(ax, crs=gdf.crs.to_string())
#Saves map
plt.savefig("image name.png", dpi=300, bbox_inches='tight', format="png", transparent=False,pad_inches = 0)
plt.close()
#Read the map
plotmap = r"image name above^^"
truthplot = plt.imread(plotmap)
#Create subplot over the map
fig, ax = plt.subplots(figsize = (6,6),linewidth = 0.1, frameon=False)
plottitle = "plot title"
ax.set_title(plottitle)
ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")
fig.tight_layout()
def animate(i):
Time.remove(Time[0])
Speed.remove(Speed[0])
scat = ax.scatter(Longs[i], Lats[i], zorder=1, alpha= 0.5, c='r', s=7)
annotation = AnchoredText(s=("Time: " + str(Time[0]) + "\n" + "Speed: " + str(Speed[0])),
prop=dict(size=8), frameon=True, loc='upper left')
annotation.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
ax.add_artist(annotation)
ax.imshow(truthplot, extent=(minx, maxx, miny, maxy), aspect='auto')
return [annotation],[scat],[Longs],[Lats]
#make the animation
ani = FuncAnimation(fig, animate,frames = savecount, interval=20, repeat = False)
ani.save(f, fps=15,writer='ffmpeg'
)
Everything else works except saving it takes WAY longer than it should, I think.
Thank you for any help!
I need use Matplotlib to draw headmaps with chinese tick labels. But the result shows incomplete tick labels as below. I don't know why it happened. I tried to change other chinese font but doesn't work. How to fix it?
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['STZhongsong']
mpl.rcParams['axes.unicode_minus'] = True
def heatmap(data, row_labels, col_labels, ax=None,
cbar_kw={}, cbarlabel="", **kwargs):
if not ax:
ax = plt.gca()
im = ax.imshow(data, **kwargs)
cbar = ax.figure.colorbar(im, ax=ax, **cbar_kw)
cbar.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
ax.set_xticks(np.arange(data.shape[1]))
ax.set_yticks(np.arange(data.shape[0]))
ax.set_xticklabels(col_labels)
ax.set_yticklabels(row_labels)
ax.tick_params(top=True, bottom=False,
labeltop=True, labelbottom=False)
plt.setp(ax.get_xticklabels(), rotation=-20, ha="right",
rotation_mode="anchor")
for edge, spine in ax.spines.items():
spine.set_visible(False)
ax.set_xticks(np.arange(data.shape[1]+1)-.5, minor=True)
ax.set_yticks(np.arange(data.shape[0]+1)-.5, minor=True)
ax.grid(which="minor", color="w", linestyle='-', linewidth=3)
ax.tick_params(which="minor", bottom=False, left=False)
return im, cbar
if __name__ == "__main__":
x,y = list("你这是干什么啦?"),list("你要吃什么?")
s = np.random.random([len(x), len(y)])
fig, ax = plt.subplots()
im, cbar = heatmap(s, x, y, ax=ax,
cmap="YlGn", cbarlabel="attention scores")
fig.tight_layout()
plt.savefig("test", dpi=300, bbox_inches = 'tight')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as mfm
import matplotlib.pyplot as plt
def heatmap(data, row_labels, col_labels, ax=None,
cbar_kw={}, cbarlabel="", **kwargs):
if not ax:
ax = plt.gca()
im = ax.imshow(data, **kwargs)
cbar = ax.figure.colorbar(im, ax=ax, **cbar_kw)
cbar.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
ax.set_xticks(np.arange(data.shape[1]))
ax.set_yticks(np.arange(data.shape[0]))
font_path = "/Downloads/ZCOOLXiaoWei-Regular.ttf"
prop = mfm.FontProperties(fname=font_path)
ax.set_xticklabels(col_labels,fontproperties=prop,fontsize=50)
ax.set_yticklabels(row_labels,fontproperties=prop,fontsize=50)
ax.tick_params(top=True, bottom=False,
labeltop=True, labelbottom=False)
plt.setp(ax.get_xticklabels(), rotation=-20, ha="right",
rotation_mode="anchor")
for edge, spine in ax.spines.items():
spine.set_visible(False)
ax.set_xticks(np.arange(data.shape[1]+1)-.5, minor=True)
ax.set_yticks(np.arange(data.shape[0]+1)-.5, minor=True)
ax.grid(which="minor", color="w", linestyle='-', linewidth=3)
ax.tick_params(which="minor", bottom=False, left=False)
return im, cbar
if __name__ == "__main__":
x,y = list("你这是干什么啦"),list("你这是干什么啦")
s = np.random.random([len(x), len(y)])
fig, ax = plt.subplots(figsize=(10,10))
im, cbar = heatmap(s, x, y, ax=ax,
cmap="YlGn", cbarlabel="attention scores")
fig.tight_layout()
plt.savefig("test", dpi=300, bbox_inches = 'tight')
plt.show()
I have made few changes in the code and used the matplotlib.font_manager to render the Chinese font.
This is an example of my code to plot and save a figure:
I'm using Python 3.7.4 and matplotlib==3.0.3.
import matplotlib.pyplot as plt
import pandas as pd
from yahoo_fin import stock_info
import statsmodels.api as sm
brk_data = stock_info.get_data("BRK-A")
with plt.style.context('dark_background'):
fig, ax = plt.subplots(figsize=(16, 9))
sm.qqplot(brk_data['adjclose'].pct_change(1).fillna(0), fit=True, line='45', ax=ax)
plt.title('QQ Plot', fontsize = 16)
ax.axvline(0, c = 'w', linestyle = "--", alpha = 0.5)
ax.grid(True,linewidth=0.30)
ax.set_xlim(4,-4)
ax.set_ylim(5,-5)
plt.savefig('qqplot.png', bbox_inches = 'tight', pad_inches = 0.4, dpi = 300, edgecolor = 'k')
plt.show()
plt.close()
This code saves and displays the plot figure correctly, as follows:
But when the plot is built inside a function, the saved picture background will stay white, making the white ticks and labels from the 'dark-background' style invisible, e.g.:
for
def qqplot2(pct, save = False):
with plt.style.context('dark_background'):
fig, ax = plt.subplots(figsize=(16, 9))
sm.qqplot(pct, fit=True, line='45', ax=ax)
plt.title('QQ Plot', fontsize = 16)
ax.axvline(0, c = 'w', linestyle = "--", alpha = 0.5)
ax.grid(True,linewidth=0.30)
ax.set_xlim(4,-4)
ax.set_ylim(5,-5)
if save == True:
plt.savefig('qqplot2.png', bbox_inches = 'tight', pad_inches = 0.4, dpi = 300, edgecolor = 'k')
plt.show()
plt.close()
else:
plt.show()
calling the function with qqplot2(brk_data['adjclose'].pct_change(1).fillna(0), save = True) will display the correct plot:
but will save the figure incorrectly:
You just need to indent your if clause in the function like this:
def qqplot2(pct, save = False):
with plt.style.context('dark_background'):
fig, ax = plt.subplots(figsize=(16, 9))
sm.qqplot(pct, fit=True, line='45', ax=ax)
plt.title('QQ Plot', fontsize = 16)
ax.axvline(0, c = 'w', linestyle = "--", alpha = 0.5)
ax.grid(True,linewidth=0.30)
ax.set_xlim(4,-4)
ax.set_ylim(5,-5)
if save == True:
plt.savefig('qqplot2.png', bbox_inches = 'tight', pad_inches = 0.4, dpi = 300, edgecolor = 'k')
plt.show()
plt.close()
else:
plt.show()
I have created 2 different figures(Fig1 and Fig2) in mathplotlib and saved them in pdf. Can anybody help me how to merger these 2 figures and create single figure. fig1 and fig2 has same x-Axis.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
def lc_fslg(target,position,axes,titel,exc_true,l_pos):
for axi in axes:
pp = PdfPages('output\ ' + 'lc_over_fuselage_'+ axi + '.pdf')
plt.figure()
plt.axis('off')
plt.text(0.5, 0.5, titel+str(axi), ha='center', va='center')
pp.savefig()
plt.close()
for kind in ['ground','flight']:
plot_load_flow(target, position, kind, axi.lower(), titel, exc_true, l_pos)
plt.savefig(pp, format='pdf', papertype='a4', orientation='landscape', bbox_inches='tight')
plt.close('all')
pp.close()
def plot_load_flow(target,position,kind,axe,titel,exc_true,l_pos):
d_ax_label = {'tx': 'Tx [daN]', 'ty': 'Ty [daN]', 'tz': 'Tz [daN]'
, 'mx': 'Mx [daNm]', 'my': 'My [daNm]', 'mz': 'Mz [daNm]'}
max_v=[]
min_v=[]
max_vM=[]
min_vM=[]
pos_env=[]
if(kind == 'ground'):
for pos in l_pos:
load_at_pos = target.uload_at(pos)
max = load_at_pos[axe].loc[(load_at_pos['position'] == pos) & (load_at_pos['type'] == 'X')].max()
min = load_at_pos[axe].loc[(load_at_pos['position'] == pos) & (load_at_pos['type'] == 'X')].min()
if(not(np.isnan(max))& (not(np.isnan(min)))):
max_v.append(max)
min_v.append(min)
pos_env.append(pos)
x_env = [position[pos] for pos in pos_env]
plt.clf()
fig1 = plt.figure(figsize=(15, 15))
plt.plot(x_env, max_v, 'b-', markersize=15,linewidth=3.5, label='envelope '+str(kind))
plt.plot(x_env, min_v, 'b-', markersize=15,linewidth=3.5)
if(kind == 'flight'):
for pos in l_pos:
load_at_pos = target.uload_at(pos)
max = load_at_pos[axe].loc[(load_at_pos['position'] == pos)
& ((load_at_pos['type'] == 'G') | (load_at_pos['type'] == 'M'))].max()
min = load_at_pos[axe].loc[(load_at_pos['position'] == pos)
& ((load_at_pos['type'] == 'G') | (load_at_pos['type'] == 'M'))].min()
if (not (np.isnan(max)) & (not (np.isnan(min)))):
max_vM.append(max)
min_vM.append(min)
pos_env.append(pos)
x_env = [position[pos] for pos in pos_env]
plt.clf()
fig2 = plt.figure(figsize=(15, 15))
plt.plot(x_env, max_v, 'b-', markersize=15,linewidth=3.5, label='envelope '+str(kind))
plt.plot(x_env, min_v, 'b-', markersize=15,linewidth=3.5)
plt.plot(x_env, max_vM, 'g-', markersize=15,linewidth=3.5, label='envelope '+str(kind))
plt.plot(x_env, min_vM, 'g-', markersize=15,linewidth=3.5)
# define plot layout
plt.yticks(fontsize=20)
plt.ylabel(d_ax_label[axe], fontsize=30)
plt.xticks(fontsize=20)
plt.xticks(x_env,pos_env,fontsize=20,rotation='vertical')
plt.xlabel('frame position', fontsize=30)
plt.title(titel, fontsize=20)
legend = plt.legend(shadow=True, prop={'size': 20})
plt.grid(True)
plt.tight_layout()