Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Color points in scatter plot of Bokeh

I have the following simple pandas.DataFrame:

df = pd.DataFrame(
    {
        "journey": ['ch1', 'ch2', 'ch2', 'ch1'],
        "cat": ['a', 'b', 'a', 'c'],
        "kpi1": [1,2,3,4],
        "kpi2": [4,3,2,1]
    }
)

Which I plot as follows:

import bokeh.plotting as bpl
import bokeh.models as bmo
bpl.output_notebook()
source = bpl.ColumnDataSource.from_df(df)
hover = bmo.HoverTool(
    tooltips=[
        ("index", "@index"),
        ('journey', '@journey'),
        ("Cat", '@cat')
    ]
)
p = bpl.figure(tools=[hover])

p.scatter(
    'kpi1', 
    'kpi2', source=source)

bpl.show(p)  # open a browser

I am failing to color code the dots according to the cat. Ultimately, I want to have the first and third point in the same color, and the second and fourth in two more different colors.

How can I achieve this using Bokeh?

like image 967
Dror Avatar asked May 15 '17 15:05

Dror


People also ask

How do I change the color of the dots on a scatter plot in R?

The different color systems available in R have been described in detail here. To change scatter plot color according to the group, you have to specify the name of the data column containing the groups using the argument groupName . Use the argument groupColors , to specify colors by hexadecimal code or by name .

How do I change the color of a scatter point in Python?

To change the color of a scatter point in matplotlib, there is the option "c" in the function scatter.


2 Answers

Here's a way that avoids manual mapping to some extent. I recently stumbled on bokeh.palettes at this github issue, as well as CategoricalColorMapper in this issue. This approach combines them. See the full list of available palettes here and the CategoricalColorMapper details here.

I had issues getting this to work directly on a pd.DataFrame, and also found it didn't work using your from_df() call. The docs show passing a DataFrame directly, and that worked for me.

import pandas as pd
import bokeh.plotting as bpl
import bokeh.models as bmo
from bokeh.palettes import d3
bpl.output_notebook()


df = pd.DataFrame(
    {
        "journey": ['ch1', 'ch2', 'ch2', 'ch1'],
        "cat": ['a', 'b', 'a', 'c'],
        "kpi1": [1,2,3,4],
        "kpi2": [4,3,2,1]
    }
)
source = bpl.ColumnDataSource(df)

# use whatever palette you want...
palette = d3['Category10'][len(df['cat'].unique())]
color_map = bmo.CategoricalColorMapper(factors=df['cat'].unique(),
                                   palette=palette)

# create figure and plot
p = bpl.figure()
p.scatter(x='kpi1', y='kpi2',
          color={'field': 'cat', 'transform': color_map},
          legend='cat', source=source)
bpl.show(p)
like image 58
Hendy Avatar answered Nov 09 '22 06:11

Hendy


For the sake of completeness, here is the adapted code using low-level chart:

import pandas as pd

import bokeh.plotting as bpl
import bokeh.models as bmo
bpl.output_notebook()


df = pd.DataFrame(
    {
        "journey": ['ch1', 'ch2', 'ch2', 'ch1'],
        "cat": ['a', 'b', 'a', 'c'],
        "kpi1": [1,2,3,4],
        "kpi2": [4,3,2,1],
        "color": ['blue', 'red', 'blue', 'green']
    }
)
df

source = bpl.ColumnDataSource.from_df(df)
hover = bmo.HoverTool(
    tooltips=[
        ('journey', '@journey'),
        ("Cat", '@cat')
    ]
)
p = bpl.figure(tools=[hover])

p.scatter(
    'kpi1', 
    'kpi2', source=source, color='color')

bpl.show(p)

Note that the colors are "hard-coded" into the data.

Here is the alternative using high-level chart:

import pandas as pd

import bokeh.plotting as bpl
import bokeh.charts as bch
bpl.output_notebook()

df = pd.DataFrame(
    {
        "journey": ['ch1', 'ch2', 'ch2', 'ch1'],
        "cat": ['a', 'b', 'a', 'c'],
        "kpi1": [1,2,3,4],
        "kpi2": [4,3,2,1]
    }
)

tooltips=[
        ('journey', '@journey'),
        ("Cat", '@cat')
    ]
scatter = bch.Scatter(df, x='kpi1', y='kpi2',
                      color='cat',
                      legend="top_right",
                      tooltips=tooltips
                     )

bch.show(scatter)
like image 23
Dror Avatar answered Nov 09 '22 08:11

Dror