I am trying to learn visualization with python and stuck here:
sns.set_context('notebook')
ax = data.plot.hist(bins=25, alpha=0.42)
ax.set_xlabel('Size (cm)');
Can anyone help me to explain what does this code sample mean?
From the documentation:
seaborn.set_context(context=None, font_scale=1, rc=None)
Set the
plotting context parameters.
This affects things like the size of the labels, lines, and other
elements of the plot, but not the overall style. The base context is
“notebook”, and the other contexts are “paper”, “talk”, and “poster”,
which are version of the notebook parameters scaled by .8, 1.3, and
1.6, respectively.
Parameters: context : dict, None, or one of {paper, notebook, talk,
poster}
A dictionary of parameters or the name of a preconfigured set.
font_scale : float, optional
Separate scaling factor to independently scale the size of the font
elements.
rc : dict, optional
Parameter mappings to override the values in the preset seaborn
context dictionaries. This only updates parameters that are considered
part of the context definition.
sns.set_context('notebook') in your example, sets up a number of parameters which will define how seaborn produces plots you generate using the module.
Related
Practicing on visualization as a Python newbie I have encountered this conceptual issue that got me thinking,
Infact I managed to change the price format on the y axis of a boxplot , from scientific notation to something more clear. Here the outputs before and after the formatting of the y axis
before
after
boxy=sns.boxplot(x="waterfront", y="price", data=df)
# my experiments success
from matplotlib.ticker import FuncFormatter
f = lambda x, pos: f'{x:.0f}'
boxy.yaxis.set_major_formatter(FuncFormatter(f))
the problem is that I realized that the attribute yaxis should refer to an AXIS object, meanwhile here what i call 'boxy' is an AXES object (at least from the seaborn documentation)
Can anyone explain it?
You're right saying that seaborn boxplot returns a matplotlib Axes object. And referring to this answer, we see Axes and Axis objects are different.
Code inspection isn't needed... but under the hood, seaborn uses matplotlib, it is noted in the GitHub here for boxplots.
when you call sns.boxplot part of drawing your plot creates Axis objects... which are objects of the matplotlib.axis module.
The y axis is in fact the first part of boxy.yaxis.set_major_formatter(FuncFormatter(f))
it is accessed with boxy.yaxis. On which you are calling the function .set_major_formatter(FuncFormatter(f)).
To see this, yaxis = boxy.get_yaxis() will return the yaxis of the boxy axes object.
EDIT IN RESPONSE TO COMMENT:
Again you're correct in the comment that this is not documented from what I could find... but if we look in the matplotlib GitHub here, we see in the YAxis class declaration:
class YAxis(Axis):
__name__ = 'yaxis'
It is just 'YAxis' renamed. Classes will assume their name in the declarative line, unless you re-specify using __name__ which was done here!
It exists!!!
boxy's yaxis inherets the set_major_formatter method from its base class, the 'Axis' class. Just to confirm this hierarchy try looking with method resolution order:
print(type(boxy.get_yaxis()).__mro__)
Should display:
(<class 'matplotlib.axis.YAxis'>, <class 'matplotlib.axis.Axis'>, <class 'matplotlib.artist.Artist'>, <class 'object'>)
In the tutorial for setting up the aesthetics of your plots, there are a few different methods:
set_style
set_context
axes_style
Each one of these accepts an rc keyword parameter dictionary. In each individual API page for the above three functions, it says:
rcdict, optional:
Parameter mappings to override the values in the preset seaborn style dictionaries. This only updates parameters that are considered part of the style definition.
Back in the tutorial page, under axes_style it goes on to say exactly how you can see what parameters are available for the rc dictionary for this one function:
If you want to see what parameters are included, you can just call the function with no arguments, which will return the current settings:
However, using this on the other functions always returns None. So, for example, I am using the following mix of matplotlib and seaborn
to set parameters:
mpl.rcParams['figure.figsize'] = [16,10]
viz_dict = {
'axes.titlesize':18,
'axes.labelsize':16,
}
sns.set_context("notebook", rc=viz_dict)
sns.set_style("whitegrid")
I also noticed that putting my dictionary in the set_style method does nothing, while, at least for those parameters, it only works in set_context. This means that they each have mutually exclusively characteristics that can be edited. However, this is not outlined anywhere in the docs.
I want to know which one of these three functions will accept a parameter for figsize. I'd also be curious to see what else they accept that might help me fine-tune things. My goal is to exclusively use the seaborn interface as often as possible. I don't need the fine tune control of things matplotlib provides, and often find it awkward anyway.
It would appear that the answer is 'none of the above'. The valid keys for set_style and set_context are listed here:
_style_keys = [
"axes.facecolor", "axes.edgecolor",
"axes.grid", "axes.axisbelow", "axes.labelcolor",
"figure.facecolor", "grid.color",
"grid.linestyle", "text.color",
"xtick.color", "ytick.color",
"xtick.direction", "ytick.direction",
"lines.solid_capstyle",
"patch.edgecolor", "patch.force_edgecolor",
"image.cmap", "font.family", "font.sans-serif",
"xtick.bottom", "xtick.top",
"ytick.left", "ytick.right",
"axes.spines.left", "axes.spines.bottom",
"axes.spines.right", "axes.spines.top",]
_context_keys = [
"font.size", "axes.labelsize",
"axes.titlesize", "xtick.labelsize",
"ytick.labelsize", "legend.fontsize",
"axes.linewidth", "grid.linewidth",
"lines.linewidth", "lines.markersize",
"patch.linewidth",
"xtick.major.width", "ytick.major.width",
"xtick.minor.width", "ytick.minor.width",
"xtick.major.size", "ytick.major.size",
"xtick.minor.size", "ytick.minor.size",]
Also note that set_style is just a convenience function which calls axes_style.
So you will have to use matplotlib.rcParams, although if the typical rcParams['figure.figsize'] = [16,10] syntax is not amenable you could of course create your own style.
I am trying to find out what what kind of arguments a function accepts. This is because I usually am unsure of what arguments a function even accepts in a first place. For example, consider a function from the the package Plotly:
fig.update_xaxes(ticks="outside")
I want to be able to know what are the different arguments ticks could be, i.e. ticks="inside" or ticks=outside.
Ideally the output would be that ticks accepts arguments such as: inside, outside, etc...
I usually get the parts pointed out by the arrows wrong because I don't know what ticks and tickson even accepts in the first place, as well as, what they do.
Right now I am using inspect. But, this doesn't tell me that I can input as arguments.
>>import inspect
>>inspect.getfullargspec(go.Figure.update_xaxes)
>>print(inspect.getsource(go.Figure.update_xaxes))
OUTPUT:
def update_xaxes(self, patch=None, selector=None, row=None, col=None, **kwargs):
"""
Perform a property update operation on all xaxis objects
that satisfy the specified selection criteria
Parameters
----------
patch: dict
Dictionary of property updates to be applied to all
xaxis objects that satisfy the selection criteria.
selector: dict or None (default None)
Dict to use as selection criteria.
xaxis objects will be selected if they contain
properties corresponding to all of the dictionary's keys, with
values that exactly match the supplied values. If None
(the default), all xaxis objects are selected.
row, col: int or None (default None)
Subplot row and column index of xaxis objects to select.
To select xaxis objects by row and column, the Figure
must have been created using plotly.subplots.make_subplots.
If None (the default), all xaxis objects are selected.
**kwargs
Additional property updates to apply to each selected
xaxis object. If a property is specified in
both patch and in **kwargs then the one in **kwargs
takes precedence.
Returns
-------
self
Returns the Figure object that the method was called on
"""
for obj in self.select_xaxes(selector=selector, row=row, col=col):
obj.update(patch, **kwargs)
return self
Using online documentation is always recommended but please keep in mind that documentation is not always generated directly from code or even if auto-generated it can contain errors or be out of date.
If you are using Jupyter Notebook you can get help on any object by running:
help(object)
If you are using an IDE like Eclipse the object options (parameters, etc..) are usually displayed to you as you type in your IDE:
And then when you are using a Figure instance:
Then when you click on it or choose ENTER when highlighting an item the parameters are inserted into your code like this:
In most IDE's you can also push CMD (Mac) or CTRL (Windows) when hovering over the library, function, object or a variable in your code (text changes into a link and the cursor changes to hand) and then click on it to go to its definition.
If the object or function is defined in another file, that file will automatically open in your IDE and the cursor will point to that object/function that you clicked.
In case of:
import plotly.graph_objects as go
fig = go.Figure(data, layout)
clicking on Figure will open _figure.py file and display this code:
I hope this helps.
In the specific case of plotly.graph_objects.Figure.update_xaxes(), you can pass in as a keyword argument anything that is accepted by the constructor of plotly.graph_objects.layout.Xaxis, and we will update the docstring and documentation to make that clearer. Note that plotly.graph_objects.layout.Xaxis accepts in its constructor what we call "magic underscores" meaning that for nested properties like title you can pass in title_font and so on, which are also not explicitly listed in that docstring. This is one of the downsides to having such a dynamic API.
I am using the basic axis.annotate(str(i)) function to show values along the points of my graph. The problem is quite quickly they get to bunched together. So I have two questions: How can I remove an annotation? And how can I make one smaller (font size)?
Here is the reference to the annotation method:
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.annotate
I have done my research and surprisingly found nothing. Cheers.
axis.annotate(str(i)) returns an axes Annotation object. You need to assign a variable to it and then you manipulate it however you want.
fig, ax = plt.subplots(1,1)
ax.plot(range(5))
text = ax.annotate(xy = (2,2), s='asdf')
# use any set_ function to change all the properties
text.set_fontsize(20)
I'm trying to find out how matplotlib and seaborn plotting functions are associated. Particularly, I'd like to know what pyplot arguments can be passed into keyword dicts marginal_kws and annot_kws in function seaborn.jointplot().
Suppose we have DataFrame data with columns c0 and c1. I guessed that joint_kws accepts arguments from pyplot.hexbin(), so when I tried to tune the appearance with arguments from there, it worked fine:
import seaborn as sns
sns.jointplot('c0', 'c1', data=data, kind='hex',
joint_kws={'gridsize':100, 'bins':'log', 'xscale':'log', 'yscale':'log'})
Then I tried to set log scale at histogram axes with an argument log=True from pyplot.hist():
sns.jointplot('c0', 'c1', data=data, kind='hex',
joint_kws={'gridsize':100, 'bins':'log', 'xscale':'log', 'yscale':'log'},
marginal_kws={'log':True})
This results in
TypeError: distplot() got an unexpected keyword argument 'log'
How to put it right?
P.S. This question is not about setting log scales in seaborn (with JointGrid, i know), but rather about passing matplotlib arguments into seaborn functions as a whole.
The dictionary of keyword arguments gets passed to distplot, which takes a dictionary for hist_kws. So you'll have to do something like marginal_kws={'hist_kws': {'log': True}}. With that said, shared log axes remain an enduring headache with jointplot, and I couldn't get something that looked good out of the box when adapting your code. Some tweaking might get it working, though.
It may also be useful to try and use JointGrid directly to avoid this kind of complexity.