Bokeh time plotting - python

I am experimenting with time plots such as this example from bokeh. Is it possible to create minor ticks for the x-axis? I tried all the different options inside p.xaxis.minor but none seemed useful.
Here's the code from example:
import pandas as pd
from bokeh.plotting import figure, output_file, show
AAPL = pd.read_csv(
"http://ichart.yahoo.com/table.csv?s=AAPL&a=0&b=1&c=2000&d=0&e=1&f=2010",
parse_dates=['Date']
)
output_file("datetime.html")
# create a new plot with a datetime axis type
p = figure(width=800, height=250, x_axis_type="datetime")
p.line(AAPL['Date'], AAPL['Close'], color='navy', alpha=0.5)
show(p)
And the image:
From what it seems it's automatically turned off, and the x-axis updates properly as you zoom in, but it would be great to include minor ticks for visualization purpose.

As of Bokeh 0.10, the BokehJS DatetimeTicker sets num_minor_ticks to zero on the internal tickers that it uses:
https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/ticking/datetime_ticker.coffee#L23
There is currently no simple way exposed to override this (You could write some JavaScript to reach in directly, but that would be a pain). I am not sure if this state of affairs is due to some inherent problem with minor ticks and datatime ranges, or if this was merely an oversight. Please make a new issue on the Bokeh GH issue tracker so it can be investigated:
https://github.com/bokeh/bokeh/issues

Related

Control the Bokeh xwheel_zoom tool using a Bokeh widget/callback

I am using xwheel_zoom (WheelZoomTool) for a Bokeh chart with datetime axis.
p = figure(x_axis_type="datetime", tools='xwheel_zoom, crosshair, undo, reset')
I provide pandas TimeStamp as the x value of this chart. For example:pd.Timestamp.now(tz='utc'). The x axis range of this chart is for the last 24 hours.
start = pd.Timestamp.now(tz='utc') - pd.Timedelta(hours=24)
Using xwheel_zoom, I could zoom in to see my chart better for a given time (e.g. last hour).
Is there any way in Bokeh I could achieve this zoom functionality by coding or connecting to the xwheel_zoom and controling it with a Bokeh widget (e.g. Bokeh dropdown)?
My objective is to have a button to click on and let it show me the zoomed in x_axis for the last hour, or show the chart between a datetime period I define. Idealy, I do not want to re-define/re-draw the chart again and just want to control the xwheel_zoom functionality.
You don't need any tools to do that. Just change the desired range in a callback. Something like:
b = Button()
def update():
p.x_range.update(start=0, end=1)
b.on_click(update)
The example will work only if used with bokeh serve. If you're not using that, you can rewrite the code to work with CustomJS and js_on_click.

Bokeh: use HTML in axis tick labels?

I am very new to Bokeh. I am trying to have clickable links on one of my plots, more precisely on the x-axis (on the ticks).
My question: is it possible to use HTML code in tick labels, for example to replace text by hypertext links?
Taking one of the examples from the documentation of Bokeh, here is my naive attempt (replacement on one of the labels, from Apples to <a>Apples</a>):
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource
from bokeh.palettes import Spectral6
from bokeh.plotting import figure
output_file("bar_colors.html")
fruits = ['<a>Apples</a>', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
counts = [5, 3, 4, 2, 4, 6]
source = ColumnDataSource(data=dict(fruits=fruits, counts=counts, color=Spectral6))
p = figure(x_range=fruits, y_range=(0,9), plot_height=350, title="Fruit Counts",
toolbar_location=None, tools="")
p.vbar(x='fruits', top='counts', width=0.9, color='color', legend="fruits", source=source)
p.xgrid.grid_line_color = None
p.legend.orientation = "horizontal"
p.legend.location = "top_center"
show(p)
It results, as you may have guessed, in a plot where I have <a>Apples</a> written as text...
How should I proceed to have a proper hypertext link?
The short answer is no. Bokeh does it's rendering on the HTML Canvas, which is a low-level bitmapped drawing area. The HTML canvas does not directly support any DOM type elements (e.g hyperlinks) on it.
There are probably a couple of ways this might be worked around:
Bokeh is extensible You could create a custom extension that renders ticks in a completely different way, i.e. by absolutely positioning real Divs on top of the canvas instead of issuing canvas drawing commands. This would require alot of bookkeeping and precise positioning. I would not describe it as trivial, and would probably need some back and forth iteration to get working, so the public mailing list would be a better place to discuss that possibility.
There is an open issue #601: Add support for click events on categorical axes that is relevant. If this were implemented, it would offer a similar capability (but without actual hyperlinks). It's possible this idea could be expanded to include any tick labels, not just categorical ones. The best place to provide your feedback on this potential feature is in the GitHub link.

Reproducing default plot behaviour of pandas.DataFrame.plot

As a frequent user of pandas, I often want to plot my data.
Using the df.plot() is very convenient, and I like the layout it gives me.
I often have the problem that when I show the generated graph to someone else, they like it, but want some tiny changes.
This often digresses into me trying to recreate the exact graph in matplotlib, which turns into a couple of hundred rows of code and it still does not work quite the same way as the df.plot()
Is there a way to get the settings for the default plotting behaviour from pandas and just ad something to the plot?
Example:
df = pd.DataFrame([1,2,3,6],index=[15,16,17,18], columns=['values'])
df.plot(kind='bar')
This little piece of code makes this pretty graph:
Trying to recreate this with matplotlib turns into a few hours of digging through documentation and still not comming up with quite the right solution.
Not to mention how many lines of configuration code it is.
import matplotlib.pyplot as plt
import matplotlib.ticker as plticker
import matplotlib.patches as mpatches
fig, ax1 = plt.subplots()
ax1.bar(df.index, df['values'], 0.4, align='center')
loc = plticker.MultipleLocator(base=1.0)
ax1.xaxis.set_major_locator(loc)
ax1.xaxis.set_ticklabels(["","15", "16", "17", "18"])
plt.show()
TLDR;
How can I easily copy the behaviour of df.plot() and extend it, without having to recreate everything manually?

Bokeh logarithmic scale for Bar chart

I know that I can do logarithmic scales with bokeh using the plotting API:
p = figure(
tools="pan,box_zoom,reset,previewsave",
y_axis_type="log", y_range=[0.001, 10**22], title="log axis example",
x_axis_label='sections', y_axis_label='particles'
)
However, I can't figure out how to get this to apply to high level charts such as Bokeh.charts.Bar. In general I'm having a lot of trouble grokking what to relationship is between a Chart and a figure. Can anyone point me to some documentation on this or explain how to modify things which are only exposed through figure and have them affect my Chart.
I am specifically going to update the documentation describing the different Bokeh APIs this week, but for now, the three Bokeh APIs in increasing order of "level":
models interface: lowest level API, base serialization layer, must put everything together everything manually
glyphs interface (bokeh.plotting): mid-level API, easily create plots/figures centered around visual glyphs with attributes tied to data
charts interface (bokeh.charts): high level API for canned/schematic statistical charts, e.g. "BoxPlot" and "Histogram".
There is no particular relation between figure and the various chart functions, except that they both produces subclasses of Plot as output.
I am not sure it is currently possible to add a log axis to the Bar plot in "charts" interface (that would be a reasonable feature to add). However it would be simple to make a boxplot "by hand" using the middle "glyphs" interface using rect or quad glyphs. Here is a quick example:
from bokeh.plotting import figure, output_file, show
output_file("bars.html")
p = figure(title="log bar example", y_axis_type="log")
p.quad(
bottom=0, top=[10**5, 10**8, 10**3],
left=[0, 2, 4], right=[1,3,5]
)
show(p)

Hiding major tick labels while showing minor tick labels in matplotlib

I would like to hide the major tick labels on my x-axis while retaining just its minor labels. The idea is that my dates are displayed in between the major ticks instead of on them by default. I have seen a few other answers to similar questions as this one and tried using their way of hiding the major ticks however I am not having much luck getting it working at all. My graph currently looks like this:
This is the formatting code I originally had for my graph before I decided I wanted to put the labels on the minor ticks.
day_fmt = '%d'
myFmt = mdates.DateFormatter(day_fmt)
ax.xaxis.set_major_formatter(myFmt)
ax.xaxis.set_major_locator(matplotlib.dates.DayLocator(interval=1))
I have attempted to get the minor ticks to show up while hiding major ticks using the code below. Here I've used an hour locator at 12pm to get the middle point of a day:
import matplotlib.ticker
ax.xaxis.set_major_formatter(ticker.NullFormatter()) #Clear major tick labels
ax.xaxis.set_minor_formatter(myFmt)
ax.xaxis.set_minor_locator(matplotlib.dates.HourLocator(interval=12))
But for some reason I get graphs that look like the picture above - with both major and minor x-axis tick labels. I also tried clearing unwanted ticks using ax.set_xticks([]). Has anyone had similar issues and fixed this or know a way to overcome this?
You could try
import matplotlib.pyplot as plt
...
plotting nitty gritty
...
plt.setp(ax.get_xmajorticklabels(), visible=False)
plt.show()

Categories

Resources