How to change the font size of the axis markers and make that bold for the following figure ? Figure is plotted with the bokeh library in python. Is there a way to get the attributes of the images like gcf where we can append the new values ?
You need the properties of the axis that have names starting with major_label_text_. The documentation: https://docs.bokeh.org/en/latest/docs/reference/models/axes.html#bokeh.models.axes.Axis.major_label_standoff
Some example:
from bokeh.plotting import figure, show
p1 = figure()
p1.xaxis.major_label_text_color = 'red'
p1.xaxis.major_label_text_font_size = '20px'
p1.line([0, 1], [0, 1])
show(p1)
Related
I would like to add multiple y axes to a bokeh plot (similar to the one achieved using matplotlib in the attached image).
Would this also be possible using bokeh? The resources I found demonstrate a second y axis.
Thanks in advance!
Best Regards,
Pranit Iyengar
Yes, this is possible. To add a new axis to the figure p use p.extra_y_ranges["my_new_axis_name"] = Range1d(...). Do not write p.extra_y_ranges = {"my_new_axis_name": Range1d(...)} if you want to add multiple axis, because this will overwrite and not extend the dictionary. Other range objects are also valid, too.
Minimal example
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import LinearAxis, Range1d
output_notebook()
data_x = [1,2,3,4,5]
data_y = [1,2,3,4,5]
color = ['red', 'green', 'magenta', 'black']
p = figure(plot_width=500, plot_height=300)
p.line(data_x, data_y, color='blue')
for i, c in enumerate(color, start=1):
name = f'extra_range_{i}'
lable = f'extra range {i}'
p.extra_y_ranges[name] = Range1d(start=0, end=10*i)
p.add_layout(LinearAxis(axis_label=lable, y_range_name=name), 'left')
p.line(data_x, data_y, color=c, y_range_name=name)
show(p)
Output
Official example
See also the twin axis example (axis) on the official webpage. This example uses the same syntax with only two axis. Another example is the twin axis example for models.
I have a Quad plot displaying 2 data-sets. I would like to add a legend to the plot, however I am not sure how to do this with the Quad glyph.
Previous examples have used 'legend' however this is now deprecated, and I've tried using
'legend_label' however this is does not work.
My ultimate goal is to use the legend to interactively display both datasets
# Convert dataframe to column data source
src1 = ColumnDataSource(Merged_Bins)
src2 = ColumnDataSource(Merged_Bins)
#------------------------------------------------------------------------------------------------
# Plot Histogram using Bokeh plotting library
#------------------------------------------------------------------------------------------------
plot = figure(y_range=Range1d(start=0, end=Max_Histogram_Value),sizing_mode="scale_width",width=3000,height= 600,
title= "Histogram Plot",
x_axis_label="Time (ms)",
y_axis_label="Count",toolbar_location = "below")
plot.yaxis.ticker = FixedTicker(ticks=list(tick_vals))
glyph1=Quad(bottom=0, top='Delay1', left='left1',
right='right1', fill_color='#FF7F00',
line_color='black', fill_alpha=0.7,line_alpha=0.5,name="Option 2")
glyph1_plot=plot.add_glyph(src1, glyph1)
glyph2=Quad(bottom=0, top='Delay2', left='left2',
right='right2', fill_color='#616261',
line_color='#616261',line_alpha=0.1, fill_alpha=0.1,name="Original Design")
plot.add_glyph(src2, glyph2)
# Add hover tool for when mouse is over data
hover1 = HoverTool(tooltips=[('Delay Envelope', '#Bin_interval'),('Count', '#Delay1'),('Count Original', '#Delay2')],mode='vline',renderers=[glyph1_plot])
plot.add_tools(hover1)
plot.legend.location = "top_left"
plot.legend.click_policy="hide"
# Set autohide to true to only show the toolbar when mouse is over plot
plot.toolbar.autohide = True
script, div = components(plot)
show(plot)
It works just fine if you use the Figure.quad method instead of manually calling Figure.add_glyph with an explicitly created instance of Quad. All legen_* arguments are parsed by glyph methods of the Figure class - the glyph classes themselves do not use them at all.
from bokeh.io import show
from bokeh.plotting import figure
p = figure()
p.quad(-1, 1, 1, -1, legend_label='Hello')
p.quad(1, 3, 3, 1, color='green', legend_label='there')
show(p)
Alternatively, if you really need the manual approach for some reason, you can also create a legend manually by creating an instance of the Legend class and by adding it to the figure with Figure.add_layout.
Also, on an unrelated note - your plot looks like it was created with vbar instead of quad because all bars seem to have the same width. If so, perhaps using vbar would be simpler in your case.
I want X-axis to be exactly the same both at the bottom and top of my figure. While the ticklabels can be duplicated using ax.tick_params(labeltop=True), it seems to be no analogous command for the label of the axis itself, as ax.xaxis.set_label_position('top') relocates the label instead of duplicating it.
All the similar questions that I found (e.g. In matplotlib, how do you display an axis on both sides of the figure?) seem to be only concerned about the ticklabels, not the axis labels.
I tried using ax.twiny() but it adds a black frame around my plot. Is there a cleaner, minimalist way of duplicating the axis label to the other side of the figure to complement the duplicated ticklabels?
EDIT: minimal working example of the black frame added by ax.twiny():
import seaborn as sns
from matplotlib import pyplot as plt
ax = sns.heatmap([[0, 1], [1, 0]], cbar=None) # no outline around the heatmap
ax.twiny() # adds black frame
(Not a matplotlib expert by any means, but regarding your edit):
sns.despine(left=True, bottom=True) will remove the spines.
You should be able to replicate the xticks, xticklabels, xlim, and xlabel on the twin Axes like so:
ax = sns.heatmap([[0, 1], [1, 0]], cbar=None) # no outline around the heatmap
ax.set_xlabel('foo')
ax1 = ax.twiny() # adds black frame
ax1.set_xticks(ax.get_xticks())
ax1.set_xticklabels(ax.get_xticklabels())
ax1.set_xlabel(ax.get_xlabel())
ax1.set_xlim(ax.get_xlim())
sns.despine(left=True, bottom=True) # remove spines
The problem which traps me is that I want to enlarge the font size in the ticker on both x and y-axis.
I am using the Bokeh as the tool for plotting. I can generate a neat plot now. But the ticker is way too small. As I went through google, I hardly find the solution. Huge thank. (Enlarge the font size within the red box)
You need the major_label_text_font_size attribute:
from bokeh.io import show
from bokeh.plotting import figure
p = figure()
p.circle(0, 0)
p.xaxis.major_label_text_font_size = "20px"
show(p)
I am new to matplotlib and trying to create and save plots from pandas dataframes via a loop. Each plot should have an identical x-axis, but different y-axis lengths and labels. I have no problem creating and saving the plots with different y-axis lengths and labels, but when I create the plots, matplotlib rescales the x-axis depending on how much space is needed for the y-axis labels on the left side of the figure.
These figures are for a technical report. I plan to place one on each page of the report and I would like to have all of the x-axes take up the same amount of space on the page.
Here is an MSPaint version of what I'm getting and what I'd like to get.
Hopefully this is enough code to help. I'm sure there are lots of non-optimal parts of this.
import pandas as pd
import matplotlib.pyplot as plt
import pylab as pl
from matplotlib import collections as mc
from matplotlib.lines import Line2D
import seaborn as sns
# elements for x-axis
start = -1600
end = 2001
interval = 200 # x-axis tick interval
xticks = [x for x in range(start, end, interval)] # create x ticks
# items needed for legend construction
lw_bins = [0,10,25,50,75,90,100] # bins for line width
lw_labels = [3,6,9,12,15,18] # line widths
def make_proxy(zvalue, scalar_mappable, **kwargs):
color = 'black'
return Line2D([0, 1], [0, 1], color=color, solid_capstyle='butt', **kwargs)
# generic image ID
img_path = r'C:\\Users\\user\\chart'
img_ID = 0
for line_subset in data:
# create line collection for this run through loop
lc = mc.LineCollection(line_subset)
# create plot and set properties
sns.set(style="ticks")
sns.set_context("notebook")
fig, ax = pl.subplots(figsize=(16, len(line_subset)*0.5)) # I want the height of the figure to change based on number of labels on y-axis
# Figure width should stay the same
ax.add_collection(lc)
ax.set_xlim(left=start, right=end)
ax.set_xticks(xticks)
ax.set_ylim(0, len(line_subset)+1)
ax.margins(0.05)
sns.despine(left=True)
ax.xaxis.set_ticks_position('bottom')
ax.set_yticks(line_subset['order'])
ax.set_yticklabels(line_subset['ylabel'])
ax.tick_params(axis='y', length=0)
# legend
proxies = [make_proxy(item, lc, linewidth=item) for item in lw_labels]
ax.legend(proxies, ['0-10%', '10-25%', '25-50%', '50-75%', '75-90%', '90-100%'], bbox_to_anchor=(1.05, 1.0),
loc=2, ncol=2, labelspacing=1.25, handlelength=4.0, handletextpad=0.5, markerfirst=False,
columnspacing=1.0)
# title
ax.text(0, len(line_subset)+2, s=str(img_ID), fontsize=20)
# save as .png images
plt.savefig(r'C:\\Users\\user\\Desktop\\chart' + str(img_ID) + '.png', dpi=300, bbox_inches='tight')
Unless you use an axes of specifically defined aspect ratio (like in an imshow plot or by calling .set_aspect("equal")), the space taken by the axes should only depend on the figure size along that direction and the spacings set to the figure.
You are therefore pretty much asking for the default behaviour and the only thing that prevents you from obtaining that is that you use bbox_inches='tight' in the savefig command.
bbox_inches='tight' will change the figure size! So don't use it and the axes will remain constant in size. `
Your figure size, defined like figsize=(16, len(line_subset)*0.5) seems to make sense according to what I understand from the question. So what remains is to make sure the axes inside the figure are the size you want them to be. You can do that by manually placing it using fig.add_axes
fig.add_axes([left, bottom, width, height])
where left, bottom, width, height are in figure coordinates ranging from 0 to 1. Or, you can adjust the spacings outside the subplot using subplots_adjust
plt.subplots_adjust(left, bottom, right, top)
To get matching x axis for the subplots (same x axis length for each subplot) , you need to share the x axis between subplots.
See the example here https://matplotlib.org/examples/pylab_examples/shared_axis_demo.html