简体   繁体   中英

Bokeh how to show negative log scale in x and y axis?

I want to plot some financials data which have very wide ranges. At first I used linear axis, however due to the extreme ranges in both x and y axis...the plot end up unusable. I know there are outliers but I don't want to exclude them from the chart.

Linear chart

Hence I'm using log scale for both x and y axis. The log scale plot was successfully created, however it shows only the positive data...all the negative data is gone from the plot. Then I did a bit of searching around and I found in Bokeh github about forcing log axes to remain positive: https://github.com/bokeh/bokeh/issues/5550

Log chart

With the info from github, is it really impossible to create a log scale which consists of negative values? What I want is the chart to be able to extend both x and y axis to negative values and be able to show the full data (hence no need to exclude the outliers).

Here is the code I have written:

p = figure(
x_axis_type = 'log',
y_axis_type = 'log',
height = 600,
sizing_mode = "stretch_width",
tools = TOOLS, 
tooltips = TOOLTIPS,
toolbar_location = "above"
)

p.xaxis.major_label_orientation = 3.14 / 4
p.xaxis[0].formatter = NumeralTickFormatter(format="0")
p.yaxis[0].formatter = NumeralTickFormatter(format="0")
p.grid.grid_line_alpha = 0.3

low_x = fundamental['Profit [%]'].min()
high_x = fundamental['Profit [%]'].max()
low_y = fundamental['Profit Growth [%]'].min()
high_y = fundamental['Profit Growth [%]'].max()

p.line(x = (low_x, 0), y = (0, 0), color = 'red', line_width = 2, line_dash = 'dashed')
p.line(x = (0, 0), y = (low_y, 0), color = 'red', line_width = 2, line_dash = 'dashed')
p.line(x = (0, high_x), y = (0, 0), color = 'green', line_width = 2, line_dash = 'dashed')
p.line(x = (0, 0), y = (0, high_y), color = 'green', line_width = 2, line_dash = 'dashed')

show(p)

The data can be just random floats as long as it contains negative values. I'm using Python 3.8.13 and Bokeh 2.4.3 on a Windows 10 machine. Cheers!

Mathematically, the log function is undefined ("infinite") at zero, and complex-valued for negative real numbers. So in the pure sense, a negative log axis is an impossibility. Some libraries (eg MPL I think) have implemented a symlog ("symmetric log") axis option that linearizes the scale in some interval around zero, and uses magnitudes for negative values, and stitches the ranges together so that things are "well defined". However, this approach is better suited for static plots that don't support panning and zooming. It would be a non-trivial amount of re-work to add it to Bokeh, and there has never been much demand for it, so no-one has ever decided to spend time on it.

Some other options:

  • If there are no zero values, plot using the absolute values of the coordinates to keep everything in the positive quadrant. Then you could use a log-log scale. You could distinguish "flipped" values by color or marker shape need be.
  • Alternatively, plot the separate quadrants in four plots in a grid plot, again using absolute values to keep values positive in each plot so that a log-log scale is possible. You could flip axes as appropriate if desired.
  • Lastly, use a linear scale, but omit the outliers. Find some other way to show outliers, eg in aa DataTable next to the plot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM