Change fontsize in holoviews or hvplot - python

How do I change fontsizes using holoviews or hvplot?
Here's a simple example of the plot I have:
# import libraries
import numpy as np
import pandas as pd
import holoviews as hv
import hvplot.pandas
hv.extension('bokeh', logo=False)
# create sample dataframe
df = pd.DataFrame({
'col1': np.random.normal(size=30),
'col2': np.random.normal(size=30),
})
# plot data with holoviews
my_plot = hv.Scatter(df, label='Scattering around')

1) You can change fontsizes by using .opts(fontsize={}) on your plot, like so:
# change fontsizes for different parts of plot
my_plot.opts(fontsize={
'title': 15,
'labels': 14,
'xticks': 10,
'yticks': 10,
})
2) With version >= 1.13 of holoviews you can scale all the fonts all at once and make legend, title, xticks larger with .opts(fontscale=1.5):
# make fonts all at once larger for your plot by the same scale
# here I've chosen fontscale=2, which makes all fonts 200% larger
my_plot.opts(fontscale=2)
3) If you would like to scale your fonts and you have a bokeh backend for your holoviews plot, you can do:
# scale fontsizes with 200%
my_plot.opts(fontsize={
'title': '200%',
'labels': '200%',
'ticks': '200%',
})
More info on all the possible parts of which you can change the fontsize can be found here: http://holoviews.org/user_guide/Customizing_Plots.html#Font-sizes

Related

Seaborn Boxplot with jittered outliers

I want a Boxplot with jittered outliers. But only the outliers not the non-outliers.
Searching the web you often find a workaround combining sns.boxplot() and sns.swarmplot().
The problem with that figure is that the outliers are drawn twice. I don't need the red ones I only need the jittered (green) ones.
Also the none-outliers are drawn. I don't need them also.
I also have a feautre request at upstream open about it. But on my current research there is no Seaborn-inbuild solution for that.
This is an MWE reproducing the boxplot shown.
#!/usr/bin/env python3
import random
import pandas
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme()
random.seed(0)
df = pandas.DataFrame({
'Vals': random.choices(range(200), k=200)})
df_outliers = pandas.DataFrame({
'Vals': random.choices(range(400, 700), k=20)})
df = pandas.concat([df, df_outliers], axis=0)
flierprops = {
'marker': 'o',
'markeredgecolor': 'red',
'markerfacecolor': 'none'
}
# Usual boxplot
ax = sns.boxplot(y='Vals', data=df, flierprops=flierprops)
# Add jitter with the swarmplot function
ax = sns.swarmplot(y='Vals', data=df, linewidth=.75, color='none', edgecolor='green')
plt.show()
Here is an approach to have jittered outliers. The jitter is similar to sns.stripplot(), not to sns.swarmplot() which uses a rather elaborate spreading algorithm. Basically, all the "line" objects of the subplot are checked whether they have a marker. The x-positions of the "lines" with a marker are moved a bit to create jitter. You might want to vary the amount of jitter, e.g. when you are working with hue.
import random
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme()
random.seed(0)
df = pd.DataFrame({
'Vals': random.choices(range(200), k=200)})
df_outliers = pd.DataFrame({
'Vals': random.choices(range(400, 700), k=20)})
df = pd.concat([df, df_outliers], axis=0)
flierprops = {
'marker': 'o',
'markeredgecolor': 'red',
'markerfacecolor': 'none'
}
# Usual boxplot
ax = sns.boxplot(y='Vals', data=df, flierprops=flierprops)
for l in ax.lines:
if l.get_marker() != '':
xs = l.get_xdata()
xs += np.random.uniform(-0.2, 0.2, len(xs))
l.set_xdata(xs)
plt.tight_layout()
plt.show()
An alternative approach could be to filter out the outliers, and then call sns.swarmplot() or sns.stripplot() only with those points. As seaborn doesn't return the values calculated to position the whiskers, you might need to calculate those again via scipy, taking into account seaborn's filtering on x and on hue.

Label to holoviews HLine

I have a bar plot with two static HLine, and would like to add a label to them (or a legend) so that they are defined on the plot. I tried something like:
eq = (
sr2.hvplot(
kind="bar",
groupby ="rl",
dynamic = False,)
* hv.HLine(0.35, name="IA1").opts(color='red')
* hv.HLine(0.2, label="IA2").opts(color='green')
)
but no label comes with the chart.
This answer to a similar question explains that it is not easy, and you need a workaround:
How do I get a full-height vertical line with a legend label in holoviews + bokeh?
You can also use parts of this solution:
https://discourse.holoviz.org/t/horizontal-spikes/117
Maybe the easiest is just to not use hv.HLine() when you would like a legend with your horizontal line, but create a manual line yourself with hv.Curve() instead:
# import libraries
import pandas as pd
import seaborn as sns
import holoviews as hv
import hvplot.pandas
hv.extension('bokeh')
# create sample dataset
df = sns.load_dataset('anscombe')
# create some horizontal lines manually defining start and end point
manual_horizontal_line = hv.Curve([[0, 10], [15, 10]], label='my_own_line')
another_horizontal_line = hv.Curve([[0, 5], [15, 5]], label='another_line')
# create scatterplot
scatter_plot = df.hvplot.scatter(x='x', y='y', groupby='dataset', dynamic=False)
# overlay manual horizontal lines on scatterplot
scatter_plot * manual_horizontal_line * another_horizontal_line
Resulting plot:
If you want text labels instead of a legend, you can use hv.Text:
import holoviews as hv
hv.extension('bokeh')
hv.Scatter(([4,6,8,10],[0.1,0.5,0.01,0.7])) * \
hv.HLine(0.35).opts(color='red') * hv.Text(9, 0.38, "IA1").opts(color='red') * \
hv.HLine(0.20).opts(color='green') * hv.Text(9, 0.23, "IA2").opts(color='green')

How to make aggregated point sizes bigger in Altair, Python?

I am working on a dashboard using Altair. I am creating 4 different plot using the same data. I am creating scatterplots using mark_circle.
How do I change the size to be size*2, or anything else?
Here is a sample:
bar = alt.Chart(df).mark_point(filled=True).encode(
x='AGE_GROUP:N',
y=alt.Y( 'PERP:N', axis=alt.Axis( values= df['PERP'].unique().tolist() )),
size = 'count()')
You can do this by adjusting the scale range for the size encoding. For example, this sets the range such that the smallest points have an area of 100 square pixels, and the largest have an area of 500 square pixels:
import altair as alt
import pandas as pd
import numpy as np
df = pd.DataFrame({
'x': np.random.randn(30),
'y': np.random.randn(30),
'count': np.random.randint(1, 5, 30)
})
alt.Chart(df).mark_point().encode(
x='x',
y='y',
size=alt.Size('count', scale=alt.Scale(range=[100, 500]))
)

HoloViews create interpolated colorful heatmap

I have created a heatmap using holoviews on top of bokeh
import numpy as np
import pandas as pd
import holoviews as hv
from holoviews import opts
hv.extension('bokeh')
df = pd.DataFrame(np.random.rand(10, 10) * 100)
heatmap = hv.HeatMap((df.columns, df.index, df))
heatmap.opts(width=500, title='Thermal map', colorbar=True, tools=['hover'], cmap='Turbo')
and got the following heatmap:
How can I make the heatmap color interpolate same as the colorbar
Like moving from pixel to pixel as a gradient
similar to:
Thanks!!
Relying on post comments I was able to interpolate heatmap, especially James A. Bednar comment.
import holoviews as hv
from holoviews import opts
from holoviews.operation.datashader import regrid
df = pd.DataFrame(np.random.rand(10, 10) * 100)
img = hv.Image((df.columns, df.index, df))
img.opts(width=500, height=500, title='Thermal map', cmap='RdYlBu_r' ,tools['hover'], colorbar=True)
inter_img = regrid(img, upsample=True, interpolation='bilinear')
img + inter_img
Thanks so much

How to autohide the Bokeh toolbar when using holoviews

The holoviews documentation mentions that the Bokeh toolbar can be hidden or moved: http://holoviews.org/user_guide/Plotting_with_Bokeh.html
The bokeh document shows how to autohide the toolbar so it only shows on mouse-over.
Is it possible to autohide the toolbar when using holoviews as it doesn't allow me to pass options like toolbar='autohide'
Any help would be most welcome.
fundYear.hvplot.bar(
x='year',
y='fundingReq',
rot=90,
).opts(
toolbar='left',
title="Funding Requested per Year",
yformatter='$%f',
)
Possible settings for the position of the toolbar are:
['above', 'below', 'left', 'right', 'disable', None]
So you can't set autohide like that, but...
1) You can use hooks to set autohide.
With hooks you can customize the plot just before it will be plotted.
def set_toolbar_autohide(plot, element):
bokeh_plot = plot.state
bokeh_plot.toolbar.autohide = True
your_plot.opts(hooks=[set_toolbar_autohide], backend='bokeh')
You can also find useful info on hooks in the FAQ:
https://holoviews.org/FAQ.html
2) Another solution would be to convert your Holoviews plot to an actual bokeh plot and then set the bokeh toolbar to autohide:
Quick solution is basically:
my_bokeh_plot = hv.render(my_hv_plot, backend='bokeh')
my_bokeh_plot.toolbar.autohide = True
Full working example of 2nd solution:
# import libraries
import numpy as np
import pandas as pd
import holoviews as hv
import hvplot.pandas
hv.extension('bokeh', logo=False)
from bokeh.plotting import show
# create sample dataframe
df = pd.DataFrame({
'col1': np.random.normal(size=30),
'col2': np.random.normal(size=30),
})
# create holoviews plot
my_hv_plot = df.hvplot.scatter(label='Scattering around', width=700)
# turn plot into bokeh plot
my_bokeh_plot = hv.render(my_hv_plot, backend='bokeh')
# set toolbar to autohide
my_bokeh_plot.toolbar.autohide = True
# show plot
show(my_bokeh_plot)

Categories

Resources