I have created a bokeh figure which uses circle glyphs and which has a lasso_select tool. This is run from within a ipython notebook.
When I view the figure (which is representing a scatter chart), I select the circles which appear as outliers.
If there a way to reference the selected data from the notebook ? I suspect that source.selected (where source is the ColumnDataSource used to build the chart) would contain the data I want, however this always is set to:
{'0d': {'flag': False, 'indices': []},
'1d': {'indices': []},
'2d': {'indices': []}}
Perhaps this is not possible ? Or perhaps I need to use a bokeh-server ? Or perhaps I should just try to concentrate on a way to dump out the selected data from the javascript ?
The reason I want to do this is that I want to get the index for those outliers and use this index to investigate other sources of data.
Any suggestions or pointers to documentation welcome !
Look at Callbacks This shows an example using the lasso tool.
Related
I'm trying to add a mapline object to a highcharter graph (ideally using hcmap as a base)--in my case, so county borders can look different than state borders.
I've seen the solution listed here, but it doesn't work for me--indeed, running the answer's example code fails to create different lines for states and counties. Meanwhile, the more complex code shown here does work, but I'm not sure what it's doing under the hood, or how I could use its method to create a mapline object of state boundaries. What kind of data do I need to add a working "mapline" series? Does anyone know a good source for one for state boundaries?
Any help would be appreciated!
UPDATE 25-09-2018
In a bid to create a simpler demo (posted here: http://jsfiddle.net/bLgj4vc7/3/) for this question, I finally discovered the root cause of the problem. I have also managed to work around it, which I have posted as an answer.
I am using standalone bokehjs in my webapp. My problem is that the renderer is not updating its line glyph with updated datasource (or at least this is what the problem looks like to me).
This jsfiddle: http://jsfiddle.net/uwnqcotg/8/ demonstrates the problem. Please ignore any bad coding conventions in it; its a quick, one-off demo.
In the fiddle, the plot is loaded with a dataseries which is rendered fine and dandy. The plot can be updated in two ways:
Update Plot Once By Overwriting CDS.data Object overwrites the ColumnDataSource.data object at one-go, thus adhering to the bokeh principle of maintaining same column lengths.
Start Stream With CDS.stream employs the ColumnDataSource.stream() and updates the plot at a regular interval with randomly generated, but incremental dataseries.
In the first approach, it looks like the glyph is being updated - the axes sure are updated in accordance with the dataseries printed in the console for reference. But, the plotted glyph and the dataseries show a mismatch. To me, it looks like the glyph plotted when the plot initialized simply re-adjusted to the new axes, though I cannot be sure.
In the second approach, again, the axes are updated, but the glyph isn't. Again, the originally plotted glyph seem to re-adjust to the new axes ranges. Moreover, the rollover attr seems to be ignored as the renderer simply keeps accumulating data.
Overall, my observation is that any data provided to the renderer during its initialization is plotted correctly, but any subsequent streamed update or even an overwrite are not. Though I may be wrong here.
On the other hand, between me and bokeh, I am inclined to believe I am doing something wrong or am missing something. So what is it?
As updated in the question, in a bid to create a simpler demo posted here http://jsfiddle.net/bLgj4vc7/3/, I ran across the root cause of this problem:
It looks like bokehjs has a bug where a renderer, once initialized with a certain length of dataset, sticks to that length even for subsequent updates in dataset. In other words,
If a renderer was initialized with an empty dataset {x:[], y:[]}, even if the renderer.data_source is updated with a populated dataset later on, the renderer sticks to the zero length and nothing is drawn on the plot.
For an initial dataset of length 5, only first 5 points will be read from any subsequent updates and the glyph will be updated accordinly. Rest of the points are not acknowledged.
I don't know whether the problem is whether renderer doesn't read beyond the initial length or whether it does but fails to redraw the glyph on the plot. The ColumnDataSource sure is updated correctly.
The fiddle linked in this answer best demonstrates the problem.
So what is the solution? At the moment, this workaround: initialize the renderer with a dataset filled with NaNs, which has a length equal or more than the maximum number of datapoints you want to plot for a single dataseries.
So, if in a line glyph, I wish to plot maximum 100 datapoints, then:
const plot = Bokeh.Plotting.figure()
const maxDataPoints = 100 // maximum number of points I want for this glyph
const emptyData = Array().fill().map(_ => NaN)
const cds = new Bokeh.ColumnDataSource({x: emptyData, y: emptyData})
const renderer = plot.line({field: 'x'}, {field: 'y'}, {source: cds, line_width: 2})
// now any subsequent updates to datasource of renderer will update its glyph on the plot.
renderer.data_source.data = {
x: dataLengthLessOrEqualToMaxDataPoints.x,
y: dataLengthLessOrEqualToMaxDataPoints.y
}
Of course, I think this behaviour of bokehjs is either a bug or I am missing an undocumented step in initialization. Either way, its worth creating an issue on github: https://github.com/bokeh/bokeh/issues/8277
This seems like a straightforward problem, yet I can't find a solution. In Sage, I've got about 30 sorted points for a scatter_plot, and I want to add the order position as a label. I know this is easy if I were working with a graph object, since I could use the vertex_labels option in plot. Is there a simple fix to get this to work for a scatter_plot, or would I need to do something like make the points vertices and keep track of the exact location of each point
Currently, you may have to use matplotlib directly or mess around with that method inside of Sage to get this. See here or here for some related questions.
I've opened Trac 20583 for this.
I was trying to allow the user to give a curve as input for some analysis. Is there a package that can be used in this regard? Basically, a GUI like paint wherein the user can draw a simple curve and which would be stored in R as a set of data points or as an equation if its a simple curve.
Thanks
Gopher
Reading mouse input
Below is a list of sample approaches to first the problem, from the most complex to simplest (IMHO).
I would recommend that you have a look at the
qtpaint
package.
Less laborious solution may involve looking at the way interactive
plots in Shiny are handled. Using the click option would
enable you to get the mouse cursor position. Together with the Shiny
framework this would provide a convenient wrapper to get mouse input
from a user.
Finally, third approach could rely on making use of the locator function available in the graphics package. Depending on what you intend to do, this may be the simplest solution as you could then use read values to inform generation of your graphic.
Generating graphics
Assuming that you got your values via the locator functionality you could attempt to draw your line using segments. It would be a little fiddly as you would have to translate your coordinates to some placement of the dot in your desired chart but this wouldn't computationally too taxing, just a matter of bring mouse pointer values to some x/y values on the chart.
If you care to update your post with a sample code and reproducible attempts of your previous work, I bet the question will receive more replies. You may find this discussion on making a reproducible example in R helpful.
I'm using the datamaps library for d3 and I have asked the question unsuccessfully there on github so I wanted to cross-post it here.
What I'm trying to do is to visualise two measures – Income Inequality (Gini) and GDP per capita – in one world map and make it possible to switch between the two views.
I am almost there. Here is my example.
On the top you can choose which measure to look at and the updating works – except that the updated map is plotted underneath the previous one and not on top. This is happening even though I'm referring to the same id with both maps.
What am I missing?
Thanks for helping me!
EDIT: I managed to get it a little bit nicer – here is the updated version – but the maps are still printed over and over again below the space where they should appear.
I made a lot of these same mistakes when I first used D3. You have to use an enter(), update(), exit() pattern. There are lots of good tutorials on how to do that. Fundamentally, your structure is not setup correctly and is going to give you trouble.
For your code, you want to do the following:
Move the initial call to map() inside the map function.
Nest the map() function inside another function where you config your variables. You need to do all your global data/variable defining here.
Inside that config function, include d3.select(#radialbuttonname) and re run the map() function to update the chart on.click.
Inside the map function, you need to create functions for .data().enter(), .data.exit().remove(), and .data().transition(). That will replace the same SVG map area with a new map rather than just appending more svg's below.
You can change the tooltips and those other elements with if/then operators and remove() inside the map() function.
That should get you on your way..