Jupyter Notebook _repr_png_ returning Matplotlib plot - python

My current project requires a lot of evaluation. For convenience, I wrote a data class with Jupyter Notebook representations. My intention was to output different indicators as text (for copy & paste) and a boxplot as it is more descriptive in some cases.
To my surprise, (only) not calling show() or close() worked. However, this feels hacky to me. Thus my question: Is this behaviour intended? And why does it work?
To clarify what I'm wondering about, I expected this to happen regardless of calling show() or not:
I know, I could simply add a plot method to the data class and call that, but this really interests me.
Simplified version of the code:
class EvaluationResult:
def __init__(self, indicators, errors):
self.indicators = indicators
self.errors = errors
def _repr_html_(self):
return f"""
<b>Indicator A:</b> {self.indicators[1]:.3f}<br>
<b>Indicator B:</b> {self.indicators[2]:.3f}"""
def _repr_png_(self):
fig = plt.figure(figsize=(8, 2))
plt.boxplot(self.errors, whis=[5, 95],
showfliers=False, vert=False)
plt.title('Error distribution')
plt.tight_layout()
# return fig -- returning the figure is not mandatory
Versions: Python v3.6.4 | Jupyter Notebook v5.4.1 | IPython v6.2.1 | Matplotlib v2.2.2

Just to clarify something first - The plot was not generated because you returned a figure, but because you called the plt.boxplot() method. Simply running the following line in its own cell will auto-generate the plot inline without a call to plt.show()
plt.boxplot(errors, whis=[5, 95], showfliers=False, vert=False)
Here is a similar question which basically states that this is the default behavior.
I've always included the line %matplotlib inline in my notebook near the imports not knowing that it was the default behavior. I believe changing that line to %matplotlib notebook will change this behavior and force you to call plt.show() and plt.figure() when needed.

Related

Put additional data on existing figure

I'm solving the optimization problem by different methods (for study).
The idea is written bellow:
instance = class_with_diff_methods()
instance.create_some_func()
instance.optimization_method_one()
instance.create_data_for_plot()
instance.display()
instance.optimization_method_two()
instance.create_data_for_plot()
instance.display()
So I wanted to add the new data iteratively, without saving and I implemented my idea this way:
`
import matplotlib.pyplot as plt
def display(self):
if not self.__plot_exists:
self.figure = plt.figure()
plt.scatter( self.data[0], self.data[1])
plt.plot( self.data[0], self.appdata)
self.figure.show()
self.__plot_exists = True
else:
plt.plot( self.data[0], self.appdata)
plt.show( block=False)`
This works, but the problem is that I don't really understand, why I even need (it necessary) using "self.figure" in the first part of the code and why I should use "plt.show()" instead of just "self.figure.show" at the last line.
I would be grateful for links, that will help me clearly understand how this works.
The plt.show() method is native from matplotlib, it is what launches the GUI. Check out their documentation if you would like to know about these types of things:
https://matplotlib.org/contents.html

How to present an object oriented code with python jupyter note book?

I'm using Jupyter notebook and I want to present my object-oriented code with it.
My problem is it doesn't recognize methods of my classes.
I mean I want to explain each part of my code so I put each method in one cell.
now when I call a method I get this error:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-17-4bb647616f28> in <module>
----> 1 s.plot_numpy_array()
AttributeError: 'Classification' object has no attribute 'plot_numpy_array'
You can see my jupyter notebook in this image:
I mean is there any way to have object-oriented code which all methods are not in a cell? or at least can explain each method separately in a clear way?
You probably want to use markdown instead:
1- create your class in one cell of code (this is the only way it will execute peoperly.
2- create markdown cells that contain the parts of code you want to highlight and their explanation:
Markdown cell:
(not rendered)
```python
def __init__(self, *args):
...
```
Blurb of prose explaining what you need to. Can include Latex, pictures, etc.
-> The code between the triple 'ticks' will render with the proper syntax highlighting.
You have to keep all the functions in the same cell, correctly indented to your class. What you try to do is not supported by Jupyter notebook.
A combination of comments and markdown might be the best alternative to have clean documentation.
You an set a cell as markdown, and use syntax highlighting with TAB, single quote(`) and triple quote (```).
You can use also use ? (question mark) or ??. It will provide excellent documentation for your classes.
Take this code for instance:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in range(5):
ax.plot(x, i * x, label='$y = %ix$' % i)
ax.legend()
plt.show()
?plt

PyCharm - Auto Completion for matplotlib (and other imported modules)

I am using PyCharm 2016.1 and Python 2.7 on Windows 10 and imported the matplotlib module.
As the matplotlib module ist very extensive and I am relatively new to Python, I hoped the Auto Complete function in PyCharm could help me to get an overview of the existent properties/ functions of an object. It would be more convenient as digging through the api documentation every time, not knowing what to look for an where to find it.
For example:
from matplotlib import pyplot as plt
fig, ax = plt.subplots()
When I type ax. there ist no auto completion for the properties, functions etc. of the axis, I only get the suggestions list.
I already tried this and imported the axis module directly with:
import matplotlib.axis as axis
or
from matplotlib.axis import Axis as axis
Smart Auto Completion and 'Collect run-time types information' is already enabled.
Is there a way to enable the auto completion like described or is there another IDE that supports that?
I believe your problem is highlighted here:
https://intellij-support.jetbrains.com/hc/en-us/community/posts/205816499-Improving-collecting-run-time-type-information-for-code-insight?sort_by=votes
Tldr return types can vary, so it cant be figured out at compile time.
Most accepted way is to use a type hint, since it can only figure out what type it as run time :
import matplotlib.axes._axes as axes
fig = plt.figure(figsize=(5,10))
ax1 = fig.add_subplot(3,1,1) # type:axes.Axes
ax1.set_xlabel('Test') <- now autocompletes
You can also try an assert isinstance:
import matplotlib.axes._axes as axes
fig = plt.figure(figsize=(5,10))
ax1 = fig.add_subplot(3,1,1)
assert isinstance(ax1, axes.Axes)
ax1.set_xlabel('Test')
It wont find the autocomplete if you do it after the method you are looking for:
ax1.set_xlabel('Test')
assert isinstance(ax1, axes.Axes)
With this, you shouldnt let isinstance dictate the control flow of your code, if you are trying to run a method that doesnt exist on an object, it should crash, however, if your different object has a method of the same name (!) then you have inadvertently reached that goal without annotations being there. So I like it better, since you want it to crash early and in the correct place. YMMV
From the doc:
Assertions should not be used to test for failure cases that can
occur because of bad user input or operating system/environment
failures, such as a file not being found. Instead, you should raise an
exception, or print an error message, or whatever is appropriate. One
important reason why assertions should only be used for self-tests of
the program is that assertions can be disabled at compile time.
If Python is started with the -O option, then assertions will be
stripped out and not evaluated. So if code uses assertions heavily,
but is performance-critical, then there is a system for turning them
off in release builds. (But don't do this unless it's really
necessary.
https://wiki.python.org/moin/UsingAssertionsEffectively
Alternatively, if you dont want to add to your code in this fashion, and have Ipython/jupyter installed through anoconda, you can get the code completion from the console by right clicking the code to be ran and choosing "execute selection in console"
In addition to Paul's answer. If you are using fig, ax = plt.subplots() , you could use figure type hint. See below example:
from matplotlib import pyplot as plt
import matplotlib.axes._axes as axes
import matplotlib.figure as figure
fig, ax = plt.subplots() # type:figure.Figure, axes.Axes
ax.
fig.

Seaborn plot is not showing [duplicate]

This question already has answers here:
Seaborn plots not showing up
(8 answers)
Closed 7 years ago.
I'm following the tutorial here for what seems like the simplest example - a linear relationship.
I'm unclear on the very permissive imports, and don't seem to be able to show my plot.
my_seaborn_test.py:
import numpy as np
import seaborn as sns
class SeabornTest(object):
def run_example(self):
sns.set(color_codes=True)
np.random.seed(sum(map(ord, "regression")))
tips = sns.load_dataset("tips")
sns.lmplot(x="size", y="tip", data=tips, x_estimator=np.mean)
On the command line:
python
from my_seaborn_test import SeabornTest
st = SeabornTest()
st.run_example()
All I get is silence and this warning:
/home/me/anaconda3/envs/myenv/lib/python3.5/site-packages/matplotlib/__init__.py:892: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
warnings.warn(self.msg_depr % (key, alt_key))
As mentioned above in the other answer, running in IPython will allow you to see it, but that isn't the only way.
The last line of your method returns a FacetGrid object, which is silently discarded after your method exits, which is why you are seeing nothing other than the warning which is produced. You will need to do something with this object (IPython automatically "prints" it when it is produced).
Change your method like so:
def run_example(self):
sns.set(color_codes=True)
np.random.seed(sum(map(ord, "regression")))
tips = sns.load_dataset("tips")
sns.lmplot(x="size", y="tip", data=tips, x_estimator=np.mean).fig.show()
Now your example will open a graphical window showing the figure
If you want to save it instead, change that last line to
sns.lmplot(x="size", y="tip", data=tips, x_estimator=np.mean).savefig("testing.png")
This sort of behavior is typical of matplotlib and thus seaborn which is built on top of matplotlib. You will have to specify what needs to be done with graphics objects (the %matplotlib inline call in IPython is actually telling IPython to catch these objects and display them).

Hold is not working for pyplot

I have a problem using pyplot. I am new to Python so sorry if I am doing some obvious mistake.
After I have plotted something using pyplot it shows the graph, but when I then try and add e.g. ylabel it will not update the current graph. It results in a new graph with only the ylabel, not previously entered information. So to me it seems to be a problem with recognizing the current graph/axis, but the ishold delivers a True statement.
My setup is Python 2.7 in Python(x,y). The problem occurs both in the Spyder IDE and the IPython Qt Console. It does however not occur in the regular IPython console (which, by constrast, is not interactive, but everything is included when using show(). When I turn off interactive in Spyder/Qt console it does not show anything after using the show() command).
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
Out[2]: [<matplotlib.lines.Line2D at 0x78ca370>]

plt.ylabel('test')
Out[3]: <matplotlib.text.Text at 0x5bd5990>

plt.ishold()
Out[4]: True
matplotlib.get_backend()
Out[6]: 'module://IPython.kernel.zmq.pylab.backend_inline'
Hope any of you have some input. Thanks.
This is one of the things were InlineBackend have to behave differently from other backend or you would have sort of a memory leak. You have to keep explicit handle to matplotlib figure and/or set close_figure to False in config. Usually pyplot is a compatibility layer for matlab for convenience, try to learn to do using the Object Oriented way.
fig,ax = subplots()
ax.plot(range(4))
ax.set_ylabel('my label')
...

Categories