how could I make my data label in chart become percentage format? - matplotlib

I want to draw a line & bar chart by matplotlib.my code is like this, you can see data label's format is number in my chart:
import matplotlib.pyplot as plt
from matplotlib import ticker
import numpy as np
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.figure(figsize=(9, 6), dpi=100)
x = ['>12 Months','6-12 Months','3-6 Months','1-3 Months','1-4 Weeks','>1 Times Per Week']
y = [0.0964,0.1607,0.4158,0.3054,0.0215,0.0001]
z = [11544,19247,49794,36572,2578,16]
plt.bar(x=x, height=z, label='Vehicles Num', color='Blue', alpha=0.7, width=0.5)
plt.legend(loc="upper left")
plt.title("Frequency Distribution of Hood Ajar/Closed Events",size=15)
plt.xlabel("Frequency",size=13)
plt.ylabel("Number of Vehicles",size=13)
ax2 = plt.twinx()
ax2.set_ylabel("Percentage",size=13)
ax2.plot(y)
ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=1))
plt.plot(x, y, "r", marker='.', c='r', ms=8, linewidth='1', label="Percentage")
plt.legend(loc="upper right")
for a, b in zip(x, y):
plt.text(a, b, b, ha='center',va='bottom',fontsize=13)
plt.show()
The result I want:
the data label list "y", can show like:9.64%, 16.07%
Many Thanks~

You can use below code i have changes may help!!(Mark use full if helps!!!)
import matplotlib.pyplot as plt
from matplotlib import ticker
import numpy as np
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.figure(figsize=(9, 6), dpi=100)
x = ['>12 Months','6-12 Months','3-6 Months','1-3 Months','1-4 Weeks','>1 Times
Per Week']
y = [0.0964,0.1607,0.4158,0.3054,0.0215,0.0001]
y=np.multiply(y,100)
z = [11544,19247,49794,36572,2578,16]
plt.bar(x=x, height=z, label='Vehicles Num', color='Blue', alpha=0.7, width=0.5)
plt.legend(loc="upper left")
plt.title("Frequency Distribution of Hood Ajar/Closed Events",size=15)
plt.xlabel("Frequency",size=13)
plt.ylabel("Number of Vehicles",size=13)
ax2 = plt.twinx()
ax2.set_ylabel("Percentage",size=13)
ax2.plot(y)
ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=1))
plt.plot(x,y, "r", marker='.', c='r', ms=8, linewidth='1', label="Percentage")
plt.legend(loc="upper right")
for a, b in zip(x, y):
plt.text(a, b,str(b) +'%', ha='center',va='bottom',fontsize=13)
plt.show()

Related

how to graph 3 3D plot next to each other in python?

how I can graph 3D graph with the following code next to each other? subplot dosen't work like a 2D plt.plot()
ax = plt.axes(projection='3d')
f0 = plt.figure(figsize=(15,5))
ax.scatter3D(X,Y ,Z,facecolor="yellow")
I want to use this code to print 3 graphs next to each other horizantaly.
This is a starting point:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.mgrid[-2:2:50j, -2:2:50j]
z = np.cos(x**2 + y**2)
fig, axs = plt.subplots(1, 3, subplot_kw={"projection": "3d"}, figsize=(10, 5))
axs[0].plot_surface(x, y, z)
axs[1].plot_wireframe(x, y, z, rstride=3, cstride=3)
axs[2].plot_surface(x, y, z, alpha=0.25)
axs[2].plot_wireframe(x, y, z, rstride=3, cstride=3, color="k", lw=0.5)
plt.show()

How to add labels to sets of seaborn boxplot

I have 2 sets of boxplots, one set in blue color and another in red color. I want the legend to show the label for each set of boxplots, i.e.
Legend:
-blue box- A, -red box- B
Added labels='A' and labels='B' within sns.boxplot(), but didn't work with error message "No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument". How do I add the labels?
enter image description here
code for the inserted image:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
x = list(range(1,13))
n = 40
index = [item for item in x for i in range(n)]
np.random.seed(123)
df = pd.DataFrame({'A': np.random.normal(30, 2, len(index)),
'B': np.random.normal(10, 2, len(index))},
index=index)
red_diamond = dict(markerfacecolor='r', marker='D')
blue_dot = dict(markerfacecolor='b', marker='o')
plt.figure(figsize=[10,5])
ax = plt.gca()
ax1 = sns.boxplot( x=df.index, y=df['A'], width=0.5, color='red', \
boxprops=dict(alpha=.5), flierprops=red_diamond, labels='A')
ax2 = sns.boxplot( x=df.index, y=df['B'], width=0.5, color='blue', \
boxprops=dict(alpha=.5), flierprops=blue_dot, labels='B')
plt.ylabel('Something')
plt.legend(loc="center", fontsize=8, frameon=False)
plt.show()
Here are the software versions I am using: seaborn version 0.11.2. matplotlib version 3.5.1. python version 3.10.1
The following approach sets a label via the boxprops, and creates a legend using part of ax.artists. (Note that ax, ax1 and ax2 of the question's code are all pointing to the same subplot, so here only ax is used.)
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
x = np.arange(1, 13)
index = np.repeat(x, 40)
np.random.seed(123)
df = pd.DataFrame({'A': np.random.normal(30, 2, len(index)),
'B': np.random.normal(10, 2, len(index))},
index=index)
red_diamond = dict(markerfacecolor='r', marker='D')
blue_dot = dict(markerfacecolor='b', marker='o')
plt.figure(figsize=[10, 5])
ax = sns.boxplot(data=df, x=df.index, y='A', width=0.5, color='red',
boxprops=dict(alpha=.5, label='A'), flierprops=red_diamond)
sns.boxplot(data=df, x=df.index, y='B', width=0.5, color='blue',
boxprops=dict(alpha=.5, label='B'), flierprops=blue_dot, ax=ax)
ax.set_ylabel('Something')
handles, labels = ax.get_legend_handles_labels()
handles = [h for h, lbl, prev in zip(handles, labels, [None] + labels) if lbl != prev]
ax.legend(handles=handles, loc="center", fontsize=8, frameon=False)
plt.show()
Alternative approaches could be:
pd.melt the dataframe to long form, so hue could be used; a problem here is that then the legend wouldn't take the alpha from the boxprops into account; also setting different fliers wouldn't be supported
create a legend from custom handles

Seaborn kdeplot change title

I have the following code:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("darkgrid")
s1, s2 = 5, 3
fig, axes = plt.subplots(s1, s2, figsize=(4*5, 5*5), sharey=True)
fig.suptitle(t="Suptitle", x=0.5, y=1-0.075, fontsize=40)
for ind1 in range(s1):
for ind2 in range(s2):
data=np.random.normal(size=100)
sns.kdeplot(data, ax=axes[ind1, ind2], bw_adjust=1,
linewidth=0.9, color="C9", alpha=0.5)
for ax, col in zip(axes[0], ["column_%d" %i for i in range(s2)]):
ax.set_title(col, size=25)
for ax, row in zip(axes[:,-1], ["row_%d" %i for i in range(s1)]):
ax.yaxis.set_label_position("right")
ax.set_ylabel(row, rotation=90, size=25)
fig.text(0.5, 0.075, 'Common x label', ha='center', size = 30)
fig.text(0.065, 0.5, 'Common y label', va='center', rotation='vertical', size = 30)
fig.show()
I expect to see Something like this: .
Bur really seaborn.kdeplot breaks my picture: it changes y label and writes the word "Density" on the left hand instead of uses my own title (row0, ..., row3) on the right hand:
How can I fix it?
Thank you in advance
You can't set the ylabel to the right because you are using subplot with shared y.
To get the plot you want, you can set the ylabels to be blank, and add the ylabel as text on the defined subplots:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("darkgrid")
s1, s2 = 5, 3
fig, axes = plt.subplots(s1, s2, figsize=(4*5, 5*5), sharey=True)
fig.suptitle(t="Suptitle", x=0.5, y=1-0.075, fontsize=40)
for ind1 in range(s1):
for ind2 in range(s2):
data=np.random.normal(size=100)
sns.kdeplot(data, ax=axes[ind1, ind2], bw_adjust=1,
linewidth=0.9, color="C9", alpha=0.5)
axes[ind1, ind2].set_ylabel("")
for ax, col in zip(axes[0], ["column_%d" %i for i in range(s2)]):
ax.set_title(col, size=25)
for ax, row in zip(axes[:,-1], ["row_%d" %i for i in range(s1)]):
ax.text(1, 0.5, row, horizontalalignment='left',
verticalalignment='center',rotation = 'vertical',
size = 25,transform=ax.transAxes)
fig.text(0.5, 0.075, 'Common x label', ha='center', size = 30)
fig.text(0.065, 0.5, 'Common y label', va='center', rotation='vertical', size = 30)
fig.show()

Custom xticks labels in loglog plot

A simple example is as follows:
import numpy as np
import numpy.random as npr
import matplotlib.pyplot as plt
N = 1000
x = np.linspace(1, 5, N)
y = npr.randint(1e16, size = N) / 1e16
y = np.sort(y)
fig, ax = plt.subplots()
ax.loglog(x, y, '.')
ax.grid(True, 'both')
Where I want to replace the xticks. So far everything I tried, failed to work:
ax.set_xticks([2, 3, 4], ['a', 'b', 'c'])
ax.xaxis.set_ticks_position('none')
ax.set_xticks([])
None of the above showed any effect. My goal is to replace the ticks with custom defined ticks (strings or integers). So instead of 2 x 10⁰ it should only be 2. Similar for other xticks.
Probably this is what you're after:
import numpy as np
import matplotlib.pyplot as plt
N = 1000
x = np.linspace(1, 5, N)
y = np.random.rand(N)
y = np.sort(y)
fig, ax = plt.subplots()
ax.loglog(x, y, '.')
ax.grid(True, 'both')
ax.set_xticks([2, 3, 4])
ax.set_xticklabels(['a', 'b', 'c'])
ax.minorticks_off()
plt.show()

matlibplot: How to add space between some subplots

How can I adjust the whitespace between some subplots? In the example below, let's say I want to eliminate all whitespace between the 1st and 2nd subplots as well as between the 3rd and 4th and increase the space between the 2nd and 3rd?
import matplotlib.pyplot as plt
import numpy as np
# Simple data to display in various forms
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
f, ax = plt.subplots(4,figsize=(10,10),sharex=True)
ax[0].plot(x, y)
ax[0].set_title('Panel: A')
ax[1].plot(x, y**2)
ax[2].plot(x, y**3)
ax[2].set_title('Panel: B')
ax[3].plot(x, y**4)
plt.tight_layout()
To keep the solution close to your code you may use create 5 subplots with the middle one being one forth in height of the others and remove that middle plot.
import matplotlib.pyplot as plt
import numpy as np
# Simple data to display in various forms
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
f, ax = plt.subplots(5,figsize=(7,7),sharex=True,
gridspec_kw=dict(height_ratios=[4,4,1,4,4], hspace=0))
ax[0].plot(x, y)
ax[0].set_title('Panel: A')
ax[1].plot(x, y**2)
ax[2].remove()
ax[3].plot(x, y**3)
ax[3].set_title('Panel: B')
ax[4].plot(x, y**4)
plt.tight_layout()
plt.show()
You would need to use GridSpec to have different spaces between plots:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
# Simple data to display in various forms
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
f = plt.figure(figsize=(10,10))
gs0 = gridspec.GridSpec(2, 1)
gs00 = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=gs0[0], hspace=0)
ax0 = f.add_subplot(gs00[0])
ax0.plot(x, y)
ax0.set_title('Panel: A')
ax1 = f.add_subplot(gs00[1], sharex=ax0)
ax1.plot(x, y**2)
gs01 = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=gs0[1], hspace=0)
ax2 = f.add_subplot(gs01[0])
ax2.plot(x, y**3)
ax2.set_title('Panel: B')
ax3 = f.add_subplot(gs01[1], sharex=ax0)
ax3.plot(x, y**4)
plt.show()