Select color for each group of data points

Code:

import pandas as pd
import numpy as np
import hvplot.pandas
import panel as pn
# pn.extension(backend='matplotlib')

y1s = np.random.random(10)
y2s = np.random.random(10)
xs = np.arange(10)
test_data = pd.DataFrame(
    {'xs':xs, 'y1s':y1s, 'y2s':y2s}
)

y1_color = pn.widgets.ColorPicker(name='y1', value='#ff0000')
y2_color = pn.widgets.ColorPicker(name='y2', value='#ff0000')

# t1s = test_data.plot.scatter(x='xs', y='y1s')
# t2s = test_data.plot.scatter(x='xs', y='y2s')
# t1s * t2s

pn.Row(
    pn.Column(y1_color, y2_color),
    pn.bind(test_data.hvplot.scatter, x='xs', y=['y1s', 'y2s'], c=[y1_color, y2_color]),
    # pn.bind(test_data.hvplot.scatter, x='xs', y='y2s', c=y2_color)
)

How should I do to assign different colors to y1s and y2s? (Just like in Origin, I can set display style for y1s and y2s separately)

Here’s one way to do it:

import pandas as pd
import numpy as np
import hvplot.pandas
import panel as pn
# pn.extension(backend='matplotlib')

y1s = np.random.random(10)
y2s = np.random.random(10)
xs = np.arange(10)
test_data = pd.DataFrame(
    {'xs':xs, 'y1s':y1s, 'y2s':y2s}
)

y1_color = pn.widgets.ColorPicker(name='y1', value='#ff0000')
y2_color = pn.widgets.ColorPicker(name='y2', value='#ff0000')

pn.Row(
    pn.Column(y1_color, y2_color),
    test_data.hvplot.scatter(x='xs', y='y1s', c=y1_color.param.value),
    test_data.hvplot.scatter(x='xs', y='y2s', c=y2_color.param.value)
)

Another way:

import pandas as pd
import numpy as np
import hvplot.pandas
import panel as pn
# pn.extension(backend='matplotlib')

y1s = np.random.random(10)
y2s = np.random.random(10)
xs = np.arange(10)
test_data = pd.DataFrame(
    {'xs':xs, 'y1s':y1s, 'y2s':y2s}
)

y1_color = pn.widgets.ColorPicker(name='y1', value='#ff0000')
y2_color = pn.widgets.ColorPicker(name='y2', value='#ff0000')

pn.Column(
    pn.Row(y1_color, y2_color),
    test_data.hvplot.scatter(x='xs', y='y1s').apply.opts(color=y1_color),
    test_data.hvplot.scatter(x='xs', y='y2s').apply.opts(color=y2_color)
)

And here are even more other ways:
https://pydeas.readthedocs.io/en/latest/holoviz_interactions/panel_to_holoviews.html
https://panel.holoviz.org/reference/panes/HoloViews.html#holoviews

Your code plots y1s and y2s in two subplots, I want to put them in the same subplot, and use colorpicker to set their color separately. Is it possible?

I checked matplotlib API, for scatter plot, it accepts multiple ys, and multiple colors for each y column, but the default bokeh backend does not support this. Thus I tried pn.extension(backend='matplotlib') in line 5, but it causes other issues and I was stuck there.

Hi @ahuang11 , I found an example to assign colors for two lines separately by bokeh,

from bokeh.layouts import column
from bokeh.models import ColorPicker
from bokeh.plotting import figure, show

plot = figure(x_range=(0, 1), y_range=(0, 1), width=350, height=350)
line1 = plot.line(x=(0,1), y=(0,1), color="red", line_width=4)
line2 = plot.line(x=(0,1), y=(1.5, 0.5), color="green", line_width=4)

picker1 = ColorPicker(title="Line Color1")
picker1.js_link('color', line1.glyph, 'line_color')
picker2 = ColorPicker(title="Line Color2")
picker2.js_link('color', line2.glyph, 'line_color')

show(column(plot, picker1, picker2))

That is the thing I want, I wonder whether it is possible by Panel.

By the way, for scatter plot:

from bokeh.layouts import column, row
from bokeh.models import ColorPicker
from bokeh.plotting import figure, show

plot = figure(x_range=(0, 1), y_range=(0, 1), width=350, height=350)
s1 = plot.scatter(x=(0,1), y=(0,1), color="red")
s2 = plot.scatter(x=(0,1), y=(1.5, 0.5), color="green")

picker1 = ColorPicker(title="scatter Color1", color='#ea3323')
print(picker1)
picker1.js_link('color', s1.glyph, 'fill_color')
picker2 = ColorPicker(title="scatter Color2", color='#377e22')
print(picker2)
picker2.js_link('color', s2.glyph, 'fill_color')

show(row(column(picker1, picker2), plot))

Yes it’s possible to; just multiply them to have them on the same subplot.

import pandas as pd
import numpy as np
import hvplot.pandas
import panel as pn
# pn.extension(backend='matplotlib')

y1s = np.random.random(10)
y2s = np.random.random(10)
xs = np.arange(10)
test_data = pd.DataFrame(
    {'xs':xs, 'y1s':y1s, 'y2s':y2s}
)

y1_color = pn.widgets.ColorPicker(name='y1', value='#ff0000')
y2_color = pn.widgets.ColorPicker(name='y2', value='#ff0000')

pn.Column(
    pn.Row(y1_color, y2_color),
    test_data.hvplot.scatter(x='xs', y='y1s').apply.opts(color=y1_color) * test_data.hvplot.scatter(x='xs', y='y2s').apply.opts(color=y2_color)
)

Great, thanks for your code, I was about to give up hvplot by simply call bokeh or plotly instead, but you gave me a reason to explore more details about this tool.

1 Like

Great to hear! FYI, hvplot is simply an extension of holoviews; that means you can use holoviews functions/methods/techniques on hvplot too!