Bokeh: dynamically change axis type (ordinal or nominal) depending on source column data










0















I am creating an interactive scatter chart that includes dropdowns for x and y axes.



However, currently it will work only when the x and y axes source columns are numericals or date objects etc. In case of string columns nothing will get displayed.



How do I alter the script so it automatically changes the axis type from nominal to ordinal - and vice versa - depending on current dropdown selection?



# -*- coding: utf-8 -*-

from os.path import dirname, join
import numpy as np
import pandas.io.sql as psql
import sqlite3 as sql
import pandas as pd

from bokeh.plotting import figure
from bokeh.layouts import layout, widgetbox
from bokeh.models import ColumnDataSource, Div
from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.io import curdoc

projects = pd.read_excel('explorer_data.xlsx')

#functions
year = lambda x : x.to_pydatetime().year

axis_map = header:header for header in list(projects)

# Create Input controls
budget = Slider(title="Minimum budget", value=80, start=0, end=200000, step=1000)
start_date = Slider(title="Project start date", start=1940, end=2019, value=1970, step=1)
end_date = Slider(title="Project end date", start=1940, end=2019, value=2019, step=1)

x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Budget")
y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Spent/Paid")

# Create Column Data Source that will be used by the plot
source = ColumnDataSource(data=dict(x=, y=, number=, title=, year=, revenue=, alpha=))

TOOLTIPS=[
("ID", "@number")
# ("Year", "@year"),
# ("$", "@revenue")
]

p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None, tools = "pan,wheel_zoom,box_zoom,reset", tooltips=TOOLTIPS)
p.circle(x="x", y="y", source=source, size=7)

def select_projects():
selected = projects[

(projects['Budget'] >= budget.value) &
(projects['Start Date'].map(year) >= start_date.value) &
(projects['End Date'].map(year) <= end_date.value)
]

return selected


def update():
df = select_projects()
x_name = axis_map[x_axis.value]
y_name = axis_map[y_axis.value]

p.xaxis.axis_label = x_axis.value
p.yaxis.axis_label = y_axis.value
p.title.text = "%d projects selected" % len(df)
source.data = dict(
x=df[x_name],
y=df[y_name],
number=df['Project ID'],
)

controls = [budget, start_date, end_date, x_axis, y_axis]
for control in controls:
control.on_change('value', lambda attr, old, new: update())

sizing_mode = 'fixed' # 'scale_width' also looks nice with this example

inputs = widgetbox(*controls, sizing_mode=sizing_mode)
l = layout([
# [desc],
[inputs, p],
], sizing_mode=sizing_mode)

update() # initial load of the data

curdoc().add_root(l)
curdoc().title = "Projects"









share|improve this question


























    0















    I am creating an interactive scatter chart that includes dropdowns for x and y axes.



    However, currently it will work only when the x and y axes source columns are numericals or date objects etc. In case of string columns nothing will get displayed.



    How do I alter the script so it automatically changes the axis type from nominal to ordinal - and vice versa - depending on current dropdown selection?



    # -*- coding: utf-8 -*-

    from os.path import dirname, join
    import numpy as np
    import pandas.io.sql as psql
    import sqlite3 as sql
    import pandas as pd

    from bokeh.plotting import figure
    from bokeh.layouts import layout, widgetbox
    from bokeh.models import ColumnDataSource, Div
    from bokeh.models.widgets import Slider, Select, TextInput
    from bokeh.io import curdoc

    projects = pd.read_excel('explorer_data.xlsx')

    #functions
    year = lambda x : x.to_pydatetime().year

    axis_map = header:header for header in list(projects)

    # Create Input controls
    budget = Slider(title="Minimum budget", value=80, start=0, end=200000, step=1000)
    start_date = Slider(title="Project start date", start=1940, end=2019, value=1970, step=1)
    end_date = Slider(title="Project end date", start=1940, end=2019, value=2019, step=1)

    x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Budget")
    y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Spent/Paid")

    # Create Column Data Source that will be used by the plot
    source = ColumnDataSource(data=dict(x=, y=, number=, title=, year=, revenue=, alpha=))

    TOOLTIPS=[
    ("ID", "@number")
    # ("Year", "@year"),
    # ("$", "@revenue")
    ]

    p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None, tools = "pan,wheel_zoom,box_zoom,reset", tooltips=TOOLTIPS)
    p.circle(x="x", y="y", source=source, size=7)

    def select_projects():
    selected = projects[

    (projects['Budget'] >= budget.value) &
    (projects['Start Date'].map(year) >= start_date.value) &
    (projects['End Date'].map(year) <= end_date.value)
    ]

    return selected


    def update():
    df = select_projects()
    x_name = axis_map[x_axis.value]
    y_name = axis_map[y_axis.value]

    p.xaxis.axis_label = x_axis.value
    p.yaxis.axis_label = y_axis.value
    p.title.text = "%d projects selected" % len(df)
    source.data = dict(
    x=df[x_name],
    y=df[y_name],
    number=df['Project ID'],
    )

    controls = [budget, start_date, end_date, x_axis, y_axis]
    for control in controls:
    control.on_change('value', lambda attr, old, new: update())

    sizing_mode = 'fixed' # 'scale_width' also looks nice with this example

    inputs = widgetbox(*controls, sizing_mode=sizing_mode)
    l = layout([
    # [desc],
    [inputs, p],
    ], sizing_mode=sizing_mode)

    update() # initial load of the data

    curdoc().add_root(l)
    curdoc().title = "Projects"









    share|improve this question
























      0












      0








      0








      I am creating an interactive scatter chart that includes dropdowns for x and y axes.



      However, currently it will work only when the x and y axes source columns are numericals or date objects etc. In case of string columns nothing will get displayed.



      How do I alter the script so it automatically changes the axis type from nominal to ordinal - and vice versa - depending on current dropdown selection?



      # -*- coding: utf-8 -*-

      from os.path import dirname, join
      import numpy as np
      import pandas.io.sql as psql
      import sqlite3 as sql
      import pandas as pd

      from bokeh.plotting import figure
      from bokeh.layouts import layout, widgetbox
      from bokeh.models import ColumnDataSource, Div
      from bokeh.models.widgets import Slider, Select, TextInput
      from bokeh.io import curdoc

      projects = pd.read_excel('explorer_data.xlsx')

      #functions
      year = lambda x : x.to_pydatetime().year

      axis_map = header:header for header in list(projects)

      # Create Input controls
      budget = Slider(title="Minimum budget", value=80, start=0, end=200000, step=1000)
      start_date = Slider(title="Project start date", start=1940, end=2019, value=1970, step=1)
      end_date = Slider(title="Project end date", start=1940, end=2019, value=2019, step=1)

      x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Budget")
      y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Spent/Paid")

      # Create Column Data Source that will be used by the plot
      source = ColumnDataSource(data=dict(x=, y=, number=, title=, year=, revenue=, alpha=))

      TOOLTIPS=[
      ("ID", "@number")
      # ("Year", "@year"),
      # ("$", "@revenue")
      ]

      p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None, tools = "pan,wheel_zoom,box_zoom,reset", tooltips=TOOLTIPS)
      p.circle(x="x", y="y", source=source, size=7)

      def select_projects():
      selected = projects[

      (projects['Budget'] >= budget.value) &
      (projects['Start Date'].map(year) >= start_date.value) &
      (projects['End Date'].map(year) <= end_date.value)
      ]

      return selected


      def update():
      df = select_projects()
      x_name = axis_map[x_axis.value]
      y_name = axis_map[y_axis.value]

      p.xaxis.axis_label = x_axis.value
      p.yaxis.axis_label = y_axis.value
      p.title.text = "%d projects selected" % len(df)
      source.data = dict(
      x=df[x_name],
      y=df[y_name],
      number=df['Project ID'],
      )

      controls = [budget, start_date, end_date, x_axis, y_axis]
      for control in controls:
      control.on_change('value', lambda attr, old, new: update())

      sizing_mode = 'fixed' # 'scale_width' also looks nice with this example

      inputs = widgetbox(*controls, sizing_mode=sizing_mode)
      l = layout([
      # [desc],
      [inputs, p],
      ], sizing_mode=sizing_mode)

      update() # initial load of the data

      curdoc().add_root(l)
      curdoc().title = "Projects"









      share|improve this question














      I am creating an interactive scatter chart that includes dropdowns for x and y axes.



      However, currently it will work only when the x and y axes source columns are numericals or date objects etc. In case of string columns nothing will get displayed.



      How do I alter the script so it automatically changes the axis type from nominal to ordinal - and vice versa - depending on current dropdown selection?



      # -*- coding: utf-8 -*-

      from os.path import dirname, join
      import numpy as np
      import pandas.io.sql as psql
      import sqlite3 as sql
      import pandas as pd

      from bokeh.plotting import figure
      from bokeh.layouts import layout, widgetbox
      from bokeh.models import ColumnDataSource, Div
      from bokeh.models.widgets import Slider, Select, TextInput
      from bokeh.io import curdoc

      projects = pd.read_excel('explorer_data.xlsx')

      #functions
      year = lambda x : x.to_pydatetime().year

      axis_map = header:header for header in list(projects)

      # Create Input controls
      budget = Slider(title="Minimum budget", value=80, start=0, end=200000, step=1000)
      start_date = Slider(title="Project start date", start=1940, end=2019, value=1970, step=1)
      end_date = Slider(title="Project end date", start=1940, end=2019, value=2019, step=1)

      x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Budget")
      y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Spent/Paid")

      # Create Column Data Source that will be used by the plot
      source = ColumnDataSource(data=dict(x=, y=, number=, title=, year=, revenue=, alpha=))

      TOOLTIPS=[
      ("ID", "@number")
      # ("Year", "@year"),
      # ("$", "@revenue")
      ]

      p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None, tools = "pan,wheel_zoom,box_zoom,reset", tooltips=TOOLTIPS)
      p.circle(x="x", y="y", source=source, size=7)

      def select_projects():
      selected = projects[

      (projects['Budget'] >= budget.value) &
      (projects['Start Date'].map(year) >= start_date.value) &
      (projects['End Date'].map(year) <= end_date.value)
      ]

      return selected


      def update():
      df = select_projects()
      x_name = axis_map[x_axis.value]
      y_name = axis_map[y_axis.value]

      p.xaxis.axis_label = x_axis.value
      p.yaxis.axis_label = y_axis.value
      p.title.text = "%d projects selected" % len(df)
      source.data = dict(
      x=df[x_name],
      y=df[y_name],
      number=df['Project ID'],
      )

      controls = [budget, start_date, end_date, x_axis, y_axis]
      for control in controls:
      control.on_change('value', lambda attr, old, new: update())

      sizing_mode = 'fixed' # 'scale_width' also looks nice with this example

      inputs = widgetbox(*controls, sizing_mode=sizing_mode)
      l = layout([
      # [desc],
      [inputs, p],
      ], sizing_mode=sizing_mode)

      update() # initial load of the data

      curdoc().add_root(l)
      curdoc().title = "Projects"






      python bokeh






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 15 '18 at 17:17









      barciewiczbarciewicz

      793313




      793313






















          0






          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53324761%2fbokeh-dynamically-change-axis-type-ordinal-or-nominal-depending-on-source-col%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53324761%2fbokeh-dynamically-change-axis-type-ordinal-or-nominal-depending-on-source-col%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Barbados

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3