I'm attempting to set the values of the x and y-axes of a plot generated using contour() but am currently unable to read specific values off of the axes as desried.
fid_list = []
for fidN in arange(frames):
offset = fidN * fid_pts
current_fid = cmplx_data[offset:offset+fid_pts]
fid_list.append(current_fid)
fid_mat = fid_list
jres_spec = abs(fftshift(fft2(fid_mat)))
max_val = jres_spec.max()/15
min_val = max_val*0.15
steps = 40
figure()
CS=contour(jres_spec,arange(min_val,max_val,(max_val-min_val)/steps))
show()
Which generates a plot like this
Previously I've been using xticks and yticks to set the values of the axes, but now the exact position on the plot has become important, so being able to read values off the axes would be very helpful which I can't doing with x/yticks.
When plotting a 1D spectrum, I use the following formula to enable me to read off the x-axis
bins = arange(828, -196, -1) #change this so that 0 value occurs at value it's meant to
x = (2000 * bins / 1024.0)/128.0
plot(x, fftshift(fft(fid_list[0])))
plt.gca().invert_xaxis()
show()
And would similarly use this for the y-axis of my 2D contour plot
ybins = arange(15, -15, -1)
y = ybins * ((1/(15*10^(-3)))/ 30.0)
But I'm having trouble integrating this into my code...
I've tried using something like this
ybins = arange(15, -15, -1)
y = ybins * ((1/(15*10^(-3)))/ 30.0)
xbins = arange(828, -196, -1)
x = (2000 * xbins / 1024.0)/128.0
fid_mat = fid_list
jres_spec = abs(fftshift(fft2(fid_mat)))
max_val = jres_spec.max()/15
min_val = max_val*0.15
steps = 40
figure()
CS=contour((x, y, jres_spec),arange(min_val,max_val,(max_val-min_val)/steps))
show()
which returned
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/dominicc/<ipython-input-34-28b34c6c069d> in <module>()
7 bins = arange(828, -196, -1) #change this so that 0 value occurs at value it's meant to
8 x = (2000 * bins / 1024.0)/128.0
----> 9 CS=contour((x_list, jres_spec),arange(min_val,max_val,(max_val-min_val)/steps))
10 show()
/usr/lib/pymodules/python2.7/matplotlib/pyplot.pyc in contour(*args, **kwargs)
2195 ax.hold(hold)
2196 try:
-> 2197 ret = ax.contour(*args, **kwargs)
2198 draw_if_interactive()
2199 finally:
/usr/lib/pymodules/python2.7/matplotlib/axes.pyc in contour(self, *args, **kwargs)
7379 if not self._hold: self.cla()
7380 kwargs['filled'] = False
-> 7381 return mcontour.QuadContourSet(self, *args, **kwargs)
7382 contour.__doc__ = mcontour.QuadContourSet.contour_doc
7383
/usr/lib/pymodules/python2.7/matplotlib/contour.pyc in __init__(self, ax, *args, **kwargs)
1110 are described in QuadContourSet.contour_doc.
1111 """
-> 1112 ContourSet.__init__(self, ax, *args, **kwargs)
1113
1114 def _process_args(self, *args, **kwargs):
/usr/lib/pymodules/python2.7/matplotlib/contour.pyc in __init__(self, ax, *args, **kwargs)
701 if self.origin == 'image': self.origin = mpl.rcParams['image.origin']
702
--> 703 self._process_args(*args, **kwargs)
704 self._process_levels()
705
/usr/lib/pymodules/python2.7/matplotlib/contour.pyc in _process_args(self, *args, **kwargs)
1123 self.zmax = args[0].zmax
1124 else:
-> 1125 x, y, z = self._contour_args(args, kwargs)
1126
1127 x0 = ma.minimum(x)
/usr/lib/pymodules/python2.7/matplotlib/contour.pyc in _contour_args(self, args, kwargs)
1167 if Nargs <= 2:
1168 z = ma.asarray(args[0], dtype=np.float64)
-> 1169 x, y = self._initialize_x_y(z)
1170 args = args[1:]
1171 elif Nargs <=4:
/usr/lib/pymodules/python2.7/matplotlib/contour.pyc in _initialize_x_y(self, z)
1230 '''
1231 if z.ndim != 2:
-> 1232 raise TypeError("Input must be a 2D array.")
1233 else:
1234 Ny, Nx = z.shape
TypeError: Input must be a 2D array.
And I'm now struggling to think of other ways I could do this.
Any ideas/suggestions?
You can get rid of the error by taking out the extra parenthesis in the call to contour:
CS=contour(x, y, jres_spec,arange(min_val,max_val,(max_val-min_val)/steps))
If that doesn't give you the plot you want, try xlim and ylim to set the axis limits directly.
Related
I'm trying to make a function for a data set. The function basically takes one of the feature names as a string, and then the function is supposed to return an x axis value and a y axis value which will be used to make a bar chart. The bar chart is supposed to show the correlation between a desired feature (in this case the sepal-length) and another fixed feature (in this case the 'species' classification).
This is what a sample of the data set looks like:
enter image description here
def correlation_group(feature):
y_axis = df[['species',feature]].groupby('species').mean()
x_axis= df.species.unique()
y = []
for i in range(1) :
y.append(y_axis[i:])
print(y)
return x_axis, y
y = 'sepal_length'
x,y = correlation_group(y)
print(y)
plt.bar(x,y)
The result I get after running this is the error:
TypeError Traceback (most recent call last)
<ipython-input-39-cd8e1ad8a982> in <module>
12 x,y = correlation_group(y)
13 print(y)
---> 14 plt.bar(x,y)
D:\anaconda3\lib\site-packages\matplotlib\pyplot.py in bar(x, height, width, bottom, align, data, **kwargs)
2485 x, height, width=0.8, bottom=None, *, align='center',
2486 data=None, **kwargs):
-> 2487 return gca().bar(
2488 x, height, width=width, bottom=bottom, align=align,
2489 **({"data": data} if data is not None else {}), **kwargs)
D:\anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, data, *args, **kwargs)
1445 def inner(ax, *args, data=None, **kwargs):
1446 if data is None:
-> 1447 return func(ax, *map(sanitize_sequence, args), **kwargs)
1448
1449 bound = new_sig.bind(ax, *args, **kwargs)
D:\anaconda3\lib\site-packages\matplotlib\axes\_axes.py in bar(self, x, height, width, bottom, align, **kwargs)
2479 args = zip(left, bottom, width, height, color, edgecolor, linewidth)
2480 for l, b, w, h, c, e, lw in args:
-> 2481 r = mpatches.Rectangle(
2482 xy=(l, b), width=w, height=h,
2483 facecolor=c,
D:\anaconda3\lib\site-packages\matplotlib\patches.py in __init__(self, xy, width, height, angle, **kwargs)
740 """
741
--> 742 Patch.__init__(self, **kwargs)
743
744 self._x0 = xy[0]
D:\anaconda3\lib\site-packages\matplotlib\patches.py in __init__(self, edgecolor, facecolor, color, linewidth, linestyle, antialiased, hatch, fill, capstyle, joinstyle, **kwargs)
86 self.set_fill(fill)
87 self.set_linestyle(linestyle)
---> 88 self.set_linewidth(linewidth)
89 self.set_antialiased(antialiased)
90 self.set_hatch(hatch)
D:\anaconda3\lib\site-packages\matplotlib\patches.py in set_linewidth(self, w)
391 w = mpl.rcParams['axes.linewidth']
392
--> 393 self._linewidth = float(w)
394 # scale the dash pattern by the linewidth
395 offset, ls = self._us_dashes
TypeError: only size-1 arrays can be converted to Python scalars
I have a tf-idf matrix in a dataframe. I ran it through tsne.
tsne_vecs_clarke2 = TSNE(n_components=3, perplexity=30.0, init='pca', learning_rate='auto').fit_transform(clarke)
clarke['component1'] = tsne_vecs_clarke2[:,0]
clarke['component2'] = tsne_vecs_clarke2[:,1]
clarke['component3'] = tsne_vecs_clarke2[:,2]
When I plotted clarke['component2'] against clarke['component2'] with the following code, I get this plot:
sns.scatterplot(x=clarke['component3'], y=clarke['component2'], hue=clarke['0inclusion'],
data=clarke).set(title="T-SNE projection ")
I would like to look at it in 3D to get more insights. I tried to plot it in 3D matplotlib but I ran into a TypeError stating that input z must be 2D, not 1D.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
x = clarke['component1']
y = clarke['component2']
z = clarke['component3']
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(x, y, z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_16936/3386285865.py in <module>
1 fig = plt.figure()
2 ax = plt.axes(projection='3d')
----> 3 ax.contour3D(x, y, z, 50, cmap='binary')
4 ax.set_xlabel('x')
5 ax.set_ylabel('y')
~\anaconda3\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py in contour(self, X, Y, Z, extend3d, stride, zdir, offset, *args, **kwargs)
2173
2174 jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
-> 2175 cset = super().contour(jX, jY, jZ, *args, **kwargs)
2176 self.add_contour_set(cset, extend3d, stride, zdir, offset)
2177
~\anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, data, *args, **kwargs)
1359 def inner(ax, *args, data=None, **kwargs):
1360 if data is None:
-> 1361 return func(ax, *map(sanitize_sequence, args), **kwargs)
1362
1363 bound = new_sig.bind(ax, *args, **kwargs)
~\anaconda3\lib\site-packages\matplotlib\axes\_axes.py in contour(self, *args, **kwargs)
6418 def contour(self, *args, **kwargs):
6419 kwargs['filled'] = False
-> 6420 contours = mcontour.QuadContourSet(self, *args, **kwargs)
6421 self._request_autoscale_view()
6422 return contours
~\anaconda3\lib\site-packages\matplotlib\contour.py in __init__(self, ax, levels, filled, linewidths, linestyles, hatches, alpha, origin, extent, cmap, colors, norm, vmin, vmax, extend, antialiased, nchunk, locator, transform, *args, **kwargs)
775 self._transform = transform
776
--> 777 kwargs = self._process_args(*args, **kwargs)
778 self._process_levels()
779
~\anaconda3\lib\site-packages\matplotlib\contour.py in _process_args(self, corner_mask, *args, **kwargs)
1364 self._corner_mask = corner_mask
1365
-> 1366 x, y, z = self._contour_args(args, kwargs)
1367
1368 _mask = ma.getmask(z)
~\anaconda3\lib\site-packages\matplotlib\contour.py in _contour_args(self, args, kwargs)
1422 args = args[1:]
1423 elif Nargs <= 4:
-> 1424 x, y, z = self._check_xyz(args[:3], kwargs)
1425 args = args[3:]
1426 else:
~\anaconda3\lib\site-packages\matplotlib\contour.py in _check_xyz(self, args, kwargs)
1450
1451 if z.ndim != 2:
-> 1452 raise TypeError(f"Input z must be 2D, not {z.ndim}D")
1453 if z.shape[0] < 2 or z.shape[1] < 2:
1454 raise TypeError(f"Input z must be at least a (2, 2) shaped array, "
TypeError: Input z must be 2D, not 1D
I am not sure how to fix this issue. Any help will be much appreciated.
If you're doing PCA you probably want a scatterplot, which you can make with ax.scatter3D(x, y, z).
If you do want this as a contour, see this answer for how to structure your data: Why does pyplot.contour() require Z to be a 2D array?
I am trying to make some graphs to gain insight on where the algorithm returns bad values so I tried to filter these values by a bin to get some sort of mean value to then get the mean and make a graph with the means.
The x (and all forms of) is a pandas dataframe and the rounding is done to get somewhat better looking bins (doesn't impact the data much as the binned values are quite large)
x_tr_g = x_stat_train_good.copy()
x_te_g = x_stat_test_good.copy()
x_tr_b = x_stat_train_bad.copy()
x_te_b = x_stat_test_bad.copy()
x_tr = x_stat_train.copy()
x_te = x_stat_test.copy()
labels = ('train actual', 'test_actual','test_good','test_bad','train_good','train_bad')
train_labels = ('train actual','train_good','train_bad')
test_labels = ('test_actual','test_good','test_bad')
x_trains = (x_tr,x_tr_g,x_tr_b)
x_tests = (x_te,x_te_g,x_te_b)
def roundup(x):
return int(math.ceil(x / 10.0)) * 10
all_x = (x_tr, x_te, x_tr_g, x_te_g, x_tr_b, x_te_b)
for x in all_x:
bins =np.linspace(x['price'].min(), x['price'].max(), 50)
for i in range(0, len(bins)):
bins[i] = roundup(bins[i])
x['bin'] = pd.cut(x['price'], bins=bins, labels=bins[1:], precision=0)
for strname in numericals:
temp = x[x[strname].notnull()]
x[strname] = temp[strname].astype(int)
for strname in numericals:
for x,label in zip(x_tests, test_labels):
df = x[['bin',strname]].groupby('bin').mean()
df = df.dropna()
plt.plot(test) #Error occurs here
plt.xlabel(strname)
plt.ylabel('price')
plt.legend(loc=2)
plt.show()
And the full error:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-6-9d00df0dee51> in <module>
3 df = x[['bin',strname]].groupby('bin').mean()
4 df = df.dropna()
----> 5 plt.plot(df)
6 plt.xlabel(strname)
7 plt.ylabel('price')
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/matplotlib/pyplot.py in plot(scalex, scaley, data, *args, **kwargs)
2793 return gca().plot(
2794 *args, scalex=scalex, scaley=scaley, **({"data": data} if data
-> 2795 is not None else {}), **kwargs)
2796
2797
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/matplotlib/axes/_axes.py in plot(self, scalex, scaley, data, *args, **kwargs)
1664 """
1665 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D._alias_map)
-> 1666 lines = [*self._get_lines(*args, data=data, **kwargs)]
1667 for line in lines:
1668 self.add_line(line)
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/matplotlib/axes/_base.py in __call__(self, *args, **kwargs)
223 this += args[0],
224 args = args[1:]
--> 225 yield from self._plot_args(this, kwargs)
226
227 def get_next_color(self):
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/matplotlib/axes/_base.py in _plot_args(self, tup, kwargs)
397 func = self._makefill
398
--> 399 ncx, ncy = x.shape[1], y.shape[1]
400 if ncx > 1 and ncy > 1 and ncx != ncy:
401 cbook.warn_deprecated(
IndexError: tuple index out of range
EDIT: added the error to hope help get an answer
I'm new at python and I'm trying to run this piece of code that found in this link below:
http://benalexkeen.com/gradient-boosting-in-python-using-scikit-learn/
When I run the first two snippets I got a bunch of errors, could anyone please correct it for me, please?. I have data and I try to draw them like this in these two snippets.
These are the two piece of code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import ensemble
from sklearn import linear_model
# Mock data
x = np.arange(0, 60)
y = map(lambda x: x / 2 + (x // 10) % 2 * 20 * x / 5 + np.random.random() * 10, x)
x = pd.DataFrame({'x': x})
# Plot mock data
plt.figure(figsize=(10, 5))
plt.scatter(x, y)
plt.show()
I got the errors that below:
RuntimeError Traceback (most recent call last)
<ipython-input-2-7f1d946a4092> in <module>
6 # Plot mock data
7 plt.figure(figsize=(10, 5))
----> 8 plt.scatter(x, y)
9 plt.show()
~\Anaconda3\lib\site-packages\matplotlib\pyplot.py in scatter(x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, data, **kwargs)
2862 vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths,
2863 verts=verts, edgecolors=edgecolors, **({"data": data} if data
-> 2864 is not None else {}), **kwargs)
2865 sci(__ret)
2866 return __ret
~\Anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, data, *args, **kwargs)
1808 "the Matplotlib list!)" % (label_namer, func.__name__),
1809 RuntimeWarning, stacklevel=2)
-> 1810 return func(ax, *args, **kwargs)
1811
1812 inner.__doc__ = _add_data_doc(inner.__doc__,
~\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in scatter(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, **kwargs)
4170 edgecolors = 'face'
4171
-> 4172 self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
4173 x = self.convert_xunits(x)
4174 y = self.convert_yunits(y)
~\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _process_unit_info(self, xdata, ydata, kwargs)
2134
2135 kwargs = _process_single_axis(xdata, self.xaxis, 'xunits', kwargs)
-> 2136 kwargs = _process_single_axis(ydata, self.yaxis, 'yunits', kwargs)
2137 return kwargs
2138
~\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _process_single_axis(data, axis, unit_name, kwargs)
2116 # We only need to update if there is nothing set yet.
2117 if not axis.have_units():
-> 2118 axis.update_units(data)
2119
2120 # Check for units in the kwargs, and if present update axis
~\Anaconda3\lib\site-packages\matplotlib\axis.py in update_units(self, data)
1465 """
1466
-> 1467 converter = munits.registry.get_converter(data)
1468 if converter is None:
1469 return False
~\Anaconda3\lib\site-packages\matplotlib\units.py in get_converter(self, x)
185 if converter is None:
186 try:
--> 187 thisx = safe_first_element(x)
188 except (TypeError, StopIteration):
189 pass
~\Anaconda3\lib\site-packages\matplotlib\cbook\__init__.py in safe_first_element(obj)
1633 except TypeError:
1634 pass
-> 1635 raise RuntimeError("matplotlib does not support generators "
1636 "as input")
1637 return next(iter(obj))
RuntimeError: matplotlib does not support generators as input
The results that I'm expecting to get below in this picture
Replace plt.scatter(x, y) with plt.scatter(x, list(y)).
The value of y represents a generator function, but matplotlib needs a list here. That worked for me on python 3.6
Convert map object to list, because in python 3 is returned iterator:
y = list(map(lambda x: x / 2 + (x // 10) % 2 * 20 * x / 5 + np.random.random() * 10, x))
I am unable to draw a FacetGrid of QQ-plots with seaborn.
I have a matrix of m rows (observations) and n columns (features), and I want to draw a QQ-plot for each feature (column) to compare it with the normal distribution.
So far, my code is like this:
import scipy.stats as ss
def qqplots(fpath, expr, title):
def quantile_plot(x, **kwargs):
x = ss.zscore(x)
qntls, xr = ss.probplot(x, dist="norm")
plt.scatter(xr, qntls, **kwargs)
expr_m = pd.melt(expr)
expr_m.columns = ["Feature", "Value"]
n_feat = len(expr_m["Feature"].value_counts().index)
n_cols = int(np.sqrt(n_feat)) + 1
g = sns.FacetGrid(expr_m, col="Feature", col_wrap=n_cols)
g.map(quantile_plot, "Value");
plt.savefig(fpath + ".pdf", bbox_inches="tight")
plt.savefig(fpath + ".png", bbox_inches="tight")
plt.close()
qqplots("lognorm_qqplot", np.log2(expr), "Log-normal qqplot")
The expr variable is a pandas DataFrame with m rows (observations) and n columns (features).
The Exception I get is the following:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-52-f9333a55702e> in <module>()
39 plt.close()
40
---> 41 qqplots("lognorm_qqplot", np.log2(expr), "Log-normal qqplot")
<ipython-input-52-f9333a55702e> in qqplots(fpath, expr, title)
34
35 g = sns.FacetGrid(expr_m, col="Feature", col_wrap=n_cols)
---> 36 g.map(quantile_plot, "Value");
37 plt.savefig(fpath + ".pdf", bbox_inches="tight")
38 plt.savefig(fpath + ".png", bbox_inches="tight")
/usr/local/lib/python3.5/site-packages/seaborn/axisgrid.py in map(self, func, *args, **kwargs)
726
727 # Draw the plot
--> 728 self._facet_plot(func, ax, plot_args, kwargs)
729
730 # Finalize the annotations and layout
/usr/local/lib/python3.5/site-packages/seaborn/axisgrid.py in _facet_plot(self, func, ax, plot_args, plot_kwargs)
810
811 # Draw the plot
--> 812 func(*plot_args, **plot_kwargs)
813
814 # Sort out the supporting information
<ipython-input-52-f9333a55702e> in quantile_plot(y, **kwargs)
25 y = ss.zscore(y)
26 qntls, xr = ss.probplot(y, dist="norm")
---> 27 plt.scatter(xr, qntls, **kwargs)
28
29 expr_m = pd.melt(expr)
/usr/local/lib/python3.5/site-packages/matplotlib/pyplot.py in scatter(x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, hold, data, **kwargs)
3249 vmin=vmin, vmax=vmax, alpha=alpha,
3250 linewidths=linewidths, verts=verts,
-> 3251 edgecolors=edgecolors, data=data, **kwargs)
3252 finally:
3253 ax.hold(washold)
/usr/local/lib/python3.5/site-packages/matplotlib/__init__.py in inner(ax, *args, **kwargs)
1810 warnings.warn(msg % (label_namer, func.__name__),
1811 RuntimeWarning, stacklevel=2)
-> 1812 return func(ax, *args, **kwargs)
1813 pre_doc = inner.__doc__
1814 if pre_doc is None:
/usr/local/lib/python3.5/site-packages/matplotlib/axes/_axes.py in scatter(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, **kwargs)
3838 y = np.ma.ravel(y)
3839 if x.size != y.size:
-> 3840 raise ValueError("x and y must be the same size")
3841
3842 s = np.ma.ravel(s) # This doesn't have to match x, y in size.
ValueError: x and y must be the same size
I achieved this, and also changed the color to use the Seaborn color palette, with the following code:
def qqplots(fpath, expr, title):
def quantile_plot(x, **kwargs):
x = ss.zscore(x)
ss.probplot(x, plot=plt)
expr_m = pd.melt(expr)
expr_m.columns = ["Feature", "Value"]
n_feat = len(expr_m["Feature"].value_counts().index)
n_cols = int(np.sqrt(n_feat)) + 1
g = sns.FacetGrid(expr_m, col="Feature", col_wrap=n_cols)
g.map(quantile_plot, "Value");
for ax in g.axes:
ax.get_lines()[0].set_markerfacecolor(sns.color_palette()[0])
ax.get_lines()[1].set_color(sns.color_palette()[3])
plt.savefig(fpath + ".pdf", bbox_inches="tight")
plt.savefig(fpath + ".png", bbox_inches="tight")
plt.close()
qqplots("lognorm_qqplot", np.log2(expr), "Log-normal qqplot")
Answering your question: "I am unable to draw a FacetGrid of QQ-plots with seaborn.", I give you here an example with dataset tips from seaborn.
To draw qqplots, one of the best approaches is to use the statsmodels library which has the qqplot function built into it. This function generates a new figure if the given ax is not passed as an argument. Therefore, using FacetGrid.map() with this function generates individual figures instead of plotting everything on the grid.
To deal with this, you can use a user-defined function in which sm.qqplots retrieves the current ax thanks to plt.gca(). Here I created a new function called qqplot_new. Here the qqplots are like test for normality of data.
from matplotlib import pyplot as plt
import seaborn as sns
import statsmodels.api as sm
tips = sns.load_dataset("tips")
def qqplot_new(x, ax=None, **kwargs):
if ax is None:
ax = plt.gca()
sm.qqplot(x, ax=ax, **kwargs)
g = sns.FacetGrid(tips, col="time", row="sex")
g.map(qqplot_new, "total_bill", line='s')
Output : Figure obtained