different element sizes with matplotlib backend - holoviews

I'm trying to accomplish a heatmap color bar to add extra info about the kdims in my heatmap. (Like the colSideColors option if you are familiar with R's heatmap.2 package.)
I can get a nice result with bokeh backend, but don't know how to get custom (different) element sizes when using matplotlib backend.
Can anyone tell me how to make the strip plot "shorter" (less "high") in the matplotlib backend example?
Setup
import pandas as pd
import numpy as np
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
# dummy data
samples = ['sample{}'.format(x) for x in range(5)]
df = pd.DataFrame(np.random.rand(5, 5),columns=samples, index=samples).reset_index()
df = df.melt(id_vars='index', var_name='y').rename(columns={'index': 'x'})
# column means
df_strip = df.groupby('x').mean().reset_index()
df_strip['y'] = 'dummy'
# make plots
heatmap = hv.HeatMap(df, kdims=['x','y'])
strip = hv.HeatMap(df_strip, kdims=['x','y'])
Result with bokeh
%%output size=100 backend='bokeh'
(strip.options(xaxis=None, yaxis=None, height=50) +
heatmap.options(xrotation=90)).cols(1)
Result with matplotlib backend
%%output size=100 backend='matplotlib'
%%opts Layout [sublabel_format='' vspace=0.1]
(strip.options(xaxis=None, yaxis=None, aspect=1) +
heatmap.options(xrotation=90, aspect=1)).cols(1)
hv.__version__
'1.10.8'

The sizing unfortunately works very differently in the two backends, which means it can be somewhat difficult to get the same behavior. In this particular case you will want to set a larger aspect on the strip plot while also telling the Layout that it should weight the aspect when computing the size of the plots. Doing that looks something like this:
%%output size=100 backend='matplotlib'
%%opts Layout [sublabel_format='' vspace=0.1 aspect_weight=1]
(strip.options(xaxis=None, yaxis=None, aspect=5) +
heatmap.options(xrotation=90, aspect=1)).cols(1)

Related

Select data from a Datashader plot

I'm using Datashader to make crossplots of different parameters due to the quantity of data I'm working with. My idea is to enable some kind of interaction that allows the user to select directly from the plot, the outliers based on the data's tendency showed these ones. I wonder if Holoviews Selection1D stream is compatible with datashader.
This code simulates what I meant:
import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews import streams
from holoviews.operation.datashader import datashade
hv.extension('bokeh')
# Tools to select data
opts.defaults(opts.Points(tools=['box_select', 'lasso_select']))
# Random points to plot
random_points = hv.Points(np.random.randn(1000))
# Holoviews
selection = streams.Selection1D(source=random_points)
# Selected points by Holoviews selection stream
selected_box = hv.DynamicMap(lambda index: random_points.iloc[index],
kdims=[], streams=[selection])
# Final Overlay
Overlay = (random_points * selected_box).opts(padding = 0.01)
Overlay
So far so good, whenever I call selection I get a matrix compounded by the index of the selected points. After Calling the Datashader plot with datashade(Overlay) , the interaction between random_points and selected_box breaks, therefore I'm not sure if this stream is compatible with datashader or if the way I use the stream is wrong!
This is what inspired my idea:
http://holoviews.org/reference/apps/bokeh/selection_stream.html#bokeh-gallery-selection-stream
Helpful example to see the possibilities. Now I know it's not necessary to extract the data from the plot... I could just do another plot using Dynamic maps and streams, either by bounds or selection1D.

change Bar Chart's ColorAttr in Bokeh 0.11

Note from maintainers: This question as originally posed concerns the obsoleted and removed bokeh.charts API. See Handling Categorical Data for information on Bar cahrts in modern Bokeh
The default color palette used in Bokeh's Bar chart's ColorAttr only has six elements and that poses obvious limitation. Supposedly one can change the Colorattr helper function with same a different palette like Spectral10
But I have a hard time figuring how to apply that to an actual chart. Does anyone have an example of how to do assign a new palette like Spectral10 to the ColorAttr function and then assign the new ColorAttr to a Bar char?
Thanks!
SH
It is actually straightforward, although it is certainly not easy to find in the documentation. You assign the palette with an argument in the Bar chart call:
from bokeh.charts import Bar
from bokeh.palettes import Spectral10
p=Bar( ... ,palette=Spectral10)
If it may be of any use, here is also a code snippet (adapted from other contributors) that I use to generate palettes with an arbitrary number of colors:
import matplotlib.cm as cm
import numpy as np
colormap =cm.get_cmap("jet")
different_colors=15
color_mapping=colormap(np.linspace(0,1,different_colors),1,True)
bokeh_palette=["#%02x%02x%02x" % (r, g, b) for r, g, b in color_mapping[:,0:3]]

How to scale figure down to a particular size in inches in matplotlib

Suppose I prepare a PDF figure in matplotlib and let us say I have specified the original dimensions of the figure to be 10x10 inches. Would it be possible to produce essentially the same figure, but scaled down to 7x7in (so that all the fonts/point sizes, etc, would scale down appropriately)?
I do understand that I can open my 10x10 file in a vector graphics editor and perform the rescaling, but I was interested whether there is some simple switch that would do this directly from matplotlib.
Use set_size_inches, like so:
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(111)
fig.set_size_inches([10,10])
ax.plot([1,3,2],[2,2,2],'ro-')
plt.savefig('10x10.png')
fig.set_size_inches([4,4])
plt.savefig('4x4.png')

How can I hide the axes in matplotlib 3d?

How can I make a 3D plot without showing the axes?
When plotting a 3d plot, Matplotlib not only draws the x, y, and z axes, it draws light gray grids on the x-y, y-z, and x-z planes. I would like to draw a "free-floating" 3D plot, with none of these elements.
Stuff I've tried:
# Doesn't work; this hides the plot, not the axes
my_3d_axes.set_visible(False)
# Doesn't do anything. Also, there's no get_zaxis() function.
my_3d_axes.get_xaxis().set_visible(False)
my_3d_axes.get_yaxis().set_visible(False)
Ben Root provided a patch that fixes this for 1.0.1. It can be found as an attachment to the last email of this thread. To quote Ben:
Ok, looks like the hiding of the 3d axes was a feature added after the v1.0 release (but before I started working on mplot3d). This patch should enable the basic feature without interfering with existing functions. To hide the axes, you would have to set the private member "_axis3don" to False, like so:
ax = plt.gca(projection='3d')
ax._axis3don = False
If you do it this way, then you will get what you want now, and your code will still be compatible with mplot3d when you upgrade (although the preferred method would be to call set_axis_on() or set_axis_off()).
I hope that helps!
Ben Root
ax.set_axis_off()
Just to provide a concrete and direct example of what was mentioned at https://stackoverflow.com/a/7363931/895245
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import mpl_toolkits.mplot3d.art3d as art3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_axis_off()
# Draw a circle on the x=0 'wall'
p = Circle((0, 0), 1, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, zdir="x")
p = Circle((0, 0), 1, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, zdir="z")
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
ax.set_zlim(-1.2, 1.2)
plt.savefig('main.png', format='png', bbox_inches='tight')
Output:
Without ax.set_axis_off() it would look like:
You will notice however that this produces an excessively large whitespace margin around the figure as it simply hides the axes but does not change the viewbox. I tried bbox_inches='tight' and it did not help as it does in 2D. How to solve that at: Remove white spaces in Axes3d (matplotlib)
Tested on matplotlib==3.2.2.

How do I show logarithmically spaced grid lines at all ticks on a log-log plot using Matplotlib?

I'm trying to plot a log-log graph that shows logarithmically spaced grid lines at all of the ticks that you see along the bottom and left hand side of the plot. I've been able to show some gridlines by using matplotlib.pyplot.grid(True), but this is only showing grid lines for me at power of 10 intervals. So as an example, here is what I'm currently getting:
I'd really like something with grid lines looking more like this, where the gridlines aren't all evenly spaced:
How would I go about achieving this in Matplotlib?
Basically, you just need to put in the parameter which="both" in the grid command so that it becomes:
matplotlib.pyplot.grid(True, which="both")
Other options for which are 'minor' and 'major' which are the major ticks (which are shown in your graph) and the minor ticks which you are missing. If you want solid lines then you can use ls="-" as a parameter to grid() as well.
Here is an example for kicks:
import numpy as np
from matplotlib import pyplot as plt
x = np.arange(0, 100, .5)
y = 2 * x**3
plt.loglog(x, y)
plt.grid(True, which="both", ls="-")
plt.show()
which generates:
More details on the Matplotlib Docs
As #Bryce says, in older version of matplotlib correct kwarg is which=majorminor. I think that solid lines with a lighter color can be better than the dotted lines.
plt.grid(True, which="majorminor", ls="-", color='0.65')
Note that in the latest version of matplotlib this argument is replaced by 'both'.
plt.grid(True, which="both", ls="-", color='0.65')

Resources