Different functions return different object types, such as FacetGrid and AxesSubplot. Why and what is the difference?

Question:

I am producing graphs with Python Seaborn. I have noticed that some functions, such as sns.lmplot() return FacetGrid objects. On the other hand, the function sns.countplot() returns an AxesSubplot object of Matplotlib. This made me question:

  1. Why does Seaborn return different objects for different graphs? (Or does it return only one type, and I am manipulating the data wrongfully?)
  2. What is the difference between these object types?

This is really confusing. For example, I used g.legend(loc='center') to modify the legend of the AxesSubplot created by sns.countplot(). It worked well. However, when I try to do it with the FacetGrid created by sns.lmplot(), I get the error ‘Legend’ object is not callable. I am currently trying to solve it, but this error is not the point of this question: here, I just want to learn about the Seaborn object types.

I am sorry if this is a beginner’s question. I googled it but I could not find anything that I can understand. Also, I apologize if I do not use the correct jargon. I am self-taught regarding Python plotting, so there is a bunch of things that I do not properly understand.

Asked By: Maria

||

Answers:

Disclaimer

I posted this question a while ago, and now, looking back at it, I see how little I knew! During my BSc and MSc, I only had very basic programming lessons and no OOP, this is why I had this kind of doubt about Seaborn and Matplotlib. Now, I’ve studied and I’m able to answer my question. Yet, the things written below may be wrong, as I am still a beginner. Please correct if I’m wrong and help me improve my answer.

Fast and clumsy notes on Object-oriented programming

The piece that I lacked was Object-Oriented Programming (OOP). Below are some concepts needed to understand the rest of the answer. But the whole story is much longer than those four bullet points.

  • Object: The basic building block of Python. All data in a program are represented by objects or by relations between them. For example, all those are individual objects: a single string, a single integer, a list. Objects have attributes (variables or methods), determined by their type/class.
  • Class: It is an user-defined type of object (in addition to the built-in types, like string or integer). Classes tell which attributes an object (of that type) must have.
  • Method: Methods are like functions that can modify and manipulate the objects of a given class.
  • Instance: An object of a given type is an instance of that class.

Matplotlib.pyplot objects

Let’s start with Matplotlib, since Seaborn is based on it. When you use pyplot, you create one instance of the class Figure and one or more instances of the class Axes.

Figure is the container of all plot elements, it is the final image. Each Axes is an individual plot (e.g., a single bar plot in a big image).

As classes, there are several methods to manipulate their instances. For example, regarding the Figure class, you can use fig.savefig() to save an image. Regarding Axes, use ax.set_xlabel() to put a label in the x-axis of a plot.

Seaborn objects

Shout-out to mwaskom, who mentioned this page in the comment above.

Seaborn has two types of functions: axes-level and figure-level. Axes-level functions return matplotlib.pyplot Axes objects. Figure-level functions return a Seaborn FacetGrid objects (it does not directly returns a matplotlib Figure object). Like my past self mentioned in the question, sns.lmplot() returns a FacetGrid, while sns.countplot() returns an Axes.

Usually there are equivalents of axes-level and figure-level functions. For instance, sns.histplot() and sns.displot() return similar histograms, but the former is an Axes and the later is a FacetGrid.

Axes and FacetGrids have distinct features and methods. An instance requires methods proper to their class and manipulating their attributes. In the question example, ax.legend() works with countplot()‘s Axes because it is appropriate for that class. It doesn’t work with sns.lmplot()‘s FacetGrid because it is not appropriate for it. For manipulating FacetGrid, you need different methods, that are not present in Matplotlib.

Again, it is worth checking this page for further info: http://seaborn.pydata.org/tutorial/function_overview.html

It is worth mentioning other two Seaborn classes: JointGrid and PairGrid. They’ll also have attributes of their own.

Why so many classes? Each of them has features that are useful in a certain situation. Figure-level functions are recommended, the image customisation is easier. Axes-level images are better when you’re going to put your Seaborn plots in a bigger and complex Matplotlib figure.

Answered By: Maria
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.