Well, yes, but actually no.

from mpl_toolkits.

mplot3d import Axes3Dfig = plt.

figure(figsize=(9, 9))ax = fig.

add_subplot(111, projection='3d')x_param = 'price_thousands'y_param = 'sqft_living'z_param = 'bedrooms'x = df[x_param]y = df[y_param] * 25z = df[z_param]ax.

set_xlabel(x_param)ax.

set_ylabel(y_param)ax.

set_zlabel(z_param)ax.

scatter(x, y, z, c='b', s=50, edgecolors='w', marker='o', alpha=0.

4);It’s 3D, but it’s not quite all we hoped.

The shifting hues and point sizes are a feature of Seaborn, but Seaborn does not support 3D scatter plots as far as I know.

Conversely, Matplotlib may be able to plot in 3-dimensions, but it does not support those shifting hues and point sizes that are so lovely and useful.

In summary, there is no solution (that I know of) which comes right out of the box ready to let us have our cake and eat t too.

If this does exist though, please do share in the comments!Lets try one more approach: surface plots.

fig = plt.

figure(figsize=(9, 9))ax = fig.

gca(projection='3d')ax.

plot_trisurf(y, x, z, cmap=plt.

cm.

viridis, linewidth=0.

2)ax.

view_init(30, 145)plt.

show();Hmm.

As it turns out, surface plots are very messy unless we sort their values.

However, while sorting the values will give us a clearer picture, it won’t necessarily give us a more useful one.

x = np.

sort(x)y = np.

sort(y)z = np.

sort(z)fig = plt.

figure(figsize=(9, 9))ax = fig.

gca(projection='3d')ax.

plot_trisurf(y, x, z, cmap=plt.

cm.

viridis, linewidth=0.

2)ax.

view_init(35, 140)plt.

show();All these variables correlate very strongly with each other, so what we end up with is this very narrow and linear shape that’s difficult to make heads or tails of.

In the end, it seems that the scatterplots provided a more effective visualization, at least for this particular dataset.

Others translate somewhat better to this medium however.

iris = sns.

load_dataset('iris')fig = plt.

figure(figsize=(9, 9))ax = fig.

gca(projection='3d')ax.

plot_trisurf(iris['sepal_length'], iris['sepal_width'], iris['petal_length'], cmap=plt.

cm.

viridis, linewidth=0.

2)ax.

view_init(30, 145)plt.

show();There are some more tricks we haven’t tried yet (such as different point shapes or animating our plot to change over time), but the fact of the matter is we’re still not close to visualizing 21 dimensions simultaneously — it’s not exactly possible.

But that doesn’t mean we can’t glean meaningful insights from our super-dimensional data.

We probably care less about all 21 dimensions of this data and more about what all that data can actually do for us, such as allowing us to more accurately predict price.

To that end, we can simply plot our error values in two dimensions.

residuals = model_1st.

residfig = sm.

graphics.

qqplot(residuals, dist=stats.

norm, line='45', fit=True)plt.

xlabel('Quantiles of Standard Normal Distribution')plt.

ylabel('Quantiles of Residuals')plt.

title('Distribution of Residuals (Best Model)')fig.

show()Error Distribution vs Normal DistributionEven if we can’t see all 21 dimensions simultaneously, there are plenty of ways that we can take slices of that data and glean meaningful insights from it.

If you know of any more, please let me know!.