matplotlib axes histogram patches - matplotlib

How do you get the object from ax.hist() and then setp for the object.
Here is what I mean:
n,bins2,patches =
ax2.hist(arra,bins=18,weights=1./bias,normed=False,color='#d9d9db')
ax2.hist.setp(edgecolor='g')
Well, obviously this doesn't work! I am getting an error:
File "./bin_data.py", line 112, in <module>
ax2.hist.setp(edgecolor='g')
AttributeError: 'function' object has no attribute 'setp'
Your help will be greatly appreciated!

Of course to change the edgecolor you may directly supply it to the histogram function
n,bins2,patches = ax2.hist(..., facecolor='#d9d9db', edgecolor="g")
To answer the question: The object to set the color to is the third return of hist, which is a container of bars
n,bins2,patches = ax2.hist(..., color='#d9d9db')
plt.setp(patches, edgecolor="g")

Related

Adding Labels to Markers on Relplot

I am a bit lost on the best approach to add labels to my markers with a seaborn relplot. I see in the matplotlib documentation that there is a axes.text() method that looks to be the right approach, but it doesn't appear that this method exists. Does seaborn behave differently than matplotlib in this sense? What would the right approach be?
Error:
AttributeError: 'numpy.ndarray' object has no attribute 'text'
Code:
line_minutes_asleep = sns.relplot(
x = "sleep_date",
y = "minutes_asleep",
kind = "line",
data = df,
height=10, # make the plot 5 units high
aspect=3
)
x = df.sleep_date
y = df.minutes_asleep
names = df.minutes_asleep
print(line_minutes_asleep.axes.text())
relplot returns a FacetGrid, which is a figure containing several subplots. The property .axes of a FacetGrid is a 2D ndarray of Axes objects. Therefore, you need to use FacetGrid.axes[i,j] to get a reference to the subplot.
If you want to write something in the first subplot (axes[0,0]), at the position x,y=(20,5), you would need to do:
import seaborn as sns
sns.set(style="ticks")
tips = sns.load_dataset("tips")
g = sns.relplot(x="total_bill", y="tip", hue="day", data=tips)
g.axes[0,0].text(20,5,"this is a text")

mpld3 produces axes property value that cannot be serialized to JSON

I am doing a scatter plot using matplotlib and trying to use mpld3 to plot it in HTML. The figure when converted to dict, produces a property edgewidths with value type array with single element of value 1. which json.dumps cannot serialize to a JSON type. I am not sure which matplotlib axes property I need to change to fix this issue or do any of these libraries need some initialization properties set? Also is mpld3 the best backend for rendering as HTML?
Sample code
fig, ax = pyplot.subplots()
ax.scatter(a, b)
fig_json = json.dumps(mpld3.fig_to_dict(fig), skipkeys=True)
Problematic dict property when pretty printing dict
{'axes': [{'axes': [{'fontsize': 10.0,
'grid': {'alpha': 1.0,
'color': '#D3D3D3',
...
'axesbgalpha': None,
...
'collections': [{'alphas': [None],
...
'edgewidths': array([1.]), <--- This property
Exception
fig_json = json.dumps(mpld3.fig_to_dict(fig), skipkeys=True)
File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
**kw).encode(obj)
File "/usr/lib/python3.5/json/encoder.py", line 198, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.5/json/encoder.py", line 256, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python3.5/json/encoder.py", line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: array([1.]) is not JSON serializable
Dependencies used
matplotlib (2.1.2)
mpld3 (0.3)

Beginner's questions about Matplotlib OO Api

I am new to Matplotlib and am struggling a bit to differentiate between the OO and pyplot interfaces. I’m actually working with the Kivy GUI framework and trying to plot 4 subplots on a single figure, to be displayed by Kivy. Here’s a snippet of my code:
def create_plot(self):
self.fig, ((self.ax0, self.ax1), (self.ax2, self.ax3)) = plt.subplots(nrows=2, ncols=2)
self.ax0.set_title("A")
self.ax0.grid(True, lw = 2, ls = '--', c = '.75')
self.ax1.set_title("B")
self.ax1.grid(True, lw = 2, ls = '--', c = '.75')
self.ax2.set_title("C")
self.ax2.grid(True, lw = 2, ls = '--', c = '.75')
self.ax3.set_title("D")
self.ax3.grid(True, lw = 2, ls = '--', c = '.75')
#plt.tight_layout()
plt.show()
canvas = self.fig.canvas
self.add_widget(canvas)
What worries me is that I am calling plt methods and assigning the results to my objects. Is plt the state machine interface and not the OO interface, or is this OK?
Secondly, I want to periodically update the plotted lines, so I have a plot method that does this:
def plot(self, xCoords, yCoords):
if len(self.ax0.lines) > 0:
self.ax0.lines.pop(0)
line = self.ax0.plot(xCoords, yCoords, color='blue')
canvas = self.fig.canvas
canvas.draw()
Does that look ok? Can I just pop the existing line, or should I reuse the existing line?
Lastly, and most difficult, if I enable:
plt.tight_layout()
I get an exception:
C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\matplotlib\tight_layout.py:225: UserWarning: tight_layout : falling back to Agg renderer
warnings.warn("tight_layout : falling back to Agg renderer")
Traceback (most recent call last):
File "main.py", line 1117, in <module>
GuiApp().run()
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\app.py", line 801, in run
self.load_kv(filename=self.kv_file)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\app.py", line 598, in load_kv
root = Builder.load_file(rfilename)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 1801, in load_file
return self.load_string(data, **kwargs)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 1880, in load_string
self._apply_rule(widget, parser.root, parser.root)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 2038, in _apply_rule
self._apply_rule(child, crule, rootrule)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 2037, in _apply_rule
self.apply(child)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 1924, in apply
self._apply_rule(widget, rule, rule)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 2038, in _apply_rule
self._apply_rule(child, crule, rootrule)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 2038, in _apply_rule
self._apply_rule(child, crule, rootrule)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\lang.py", line 2035, in _apply_rule
child = cls(__no_builder=True)
File "C:\SVNProj\Raggio\trunk\hostconsole\gui\mygraph.py", line 127, in __init__
self.create_plot()
File "C:\SVNProj\Raggio\trunk\hostconsole\gui\mygraph.py", line 224, in create_plot
self.add_widget(canvas)
File "C:\Kivy-1.9.0-py3.4-win32-x64\Python34\lib\site-packages\kivy\uix\boxlayout.py", line 211, in add_widget
widget.bind(
AttributeError: 'FigureCanvasAgg' object has no attribute 'bind'
Can anyone help with that please?
Best regards
David
Original post
regarding def create_plot
plt.subplots() is just a wrapper around creating a new figure and adding subplots (axes) to that figure, so that is safe to use in any context AFAIK
regarding updating lines vs creating new lines.
Popping off and creating a new line with a call to axes.plot() will work, but will be slower than just using the existing line artist and calling artist.set_data(x_data, y_data)
Regarding the tight_layout issue
Consider just calling self.fig.tight_layout() instead of plt.tight_layout(), as plt.tight_layout() might be grabbing the wrong figure
Update based on discussion in comments:
Since you are plotting one line per panel, I would suggest adding these four lines to your create_plot method to save the LineArtist's that are created by the axes.plot() method:
self.line0, = self.ax0.plot([], [], 'b')
self.line1, = self.ax1.plot([], [], 'b')
self.line2, = self.ax2.plot([], [], 'b')
self.line3, = self.ax3.plot([], [], 'b')
Then in the plot method you can just do this:
self.line0.set_data(xCoords, yCoords)
Though I seem to be struggling to remember how to make ax0 automatically update its limits based on the xCoords and yCoords. I thought that it was as simple as self.ax0.relim(), but that is not working in my jupyter notebook right now. Hmm.

PyPlot, PyCall Legend Font Size from Julia

When I try and change the legend fontsize using PyPlot from julia, I get an error message saying "Pyerror..got an unexpected key word "'fontsize'". This happens when I try both of the standard formulations shown below:
ax[:legend]( ("Data", "Model Predictions"),fontsize=4,loc=4 )
ax[:legend]( ("Data", "Model Predictions"),prop={fontsize: "small"},loc=4 )
Note that changing fontsize works fine with other objects e.g. xlabel
Any ideas?
Does this work for you?
using PyPlot
fig, ax = PyPlot.subplots()
ax[:plot](rand(10), rand(10), label = "Data")
ax[:legend](loc="best", fontsize=4)
If not, what versions of Julia, PyPlot, PyCall, and Python are you on?
The help for legend states that:
prop : None or :class:matplotlib.font_manager.FontProperties or dict
The font properties of the legend. If None (default), the current
:data:matplotlib.rcParams will be used.
So the prob keyword argument expects a dict with font properties. Dicts is constructed in julia as [key => val]. This dict can then contain the properties. The property you would like to set is size and not fontsize because the prob keyword argument only contains font properties.
ax[:legend](("Data", "Model Predictions"), prop=["size" => "small"], loc=4)
In the end the above two suggestions didn't work (I think it's a version issue). But this did:
using PyPlot
#pyimport matplotlib.pyplot as plt
#pyimport matplotlib.font_manager as fm
prop = fm.FontProperties(size=9)
fig, ax = PyPlot.subplots()
ax[:plot](rand(10), rand(10), label = "Data")
ax[:legend](loc="best", prop=prop)

How to get the AxesImages from matplotlib

all, I use the such code to plot the images
import matplotlib.pyplot as plt
plt.imshow(array,cmap='jet')
plt.show()
however, now I want to get the handle (im) of im=plt.imshow(array,cmap='jet')
How can I get the handle of im if I ignore the handle in the second step.
You can call the method get_images() on the ax.
Example code:
ax = plt.gca()
ax.imshow(array)
ax.get_images() # returns a list of AxesImage objects if any.
You can retrieve all the children present on the axes and filter on the object type.
Like:
ax = plt.gca()
imgs = [obj for obj in ax.get_children() if isinstance(obj, mpl.image.AxesImage)]
If you have only one AxesImage on the axes it returns a list containing one object, for example:
[<matplotlib.image.AxesImage at 0x7be6400>]