# Providing data for a multi line from a dataframe? Having trouble figuring out how to restructure the dataframe / use multi\_line's syntax

**URL:** <https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038>\
**Category:** Community Support\
**Created:** [March 29, 2020, 2:14am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038 "2020-03-29T02:14:57Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 29, 2020, 2:14am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/1 "2020-03-29T02:14:57Z")

</div>

I’ve got a big dataframe called `dataset` which kinda looks like this:

| Year | New\_ID | Peak\_change |
| --- | --- | --- |
| 1980 | 1 | 1 |
| 1980 | 2 | 0.985478 |
| 1980 | 3 | 0.974417 |
| 1990 | 1 | 1 |
| 1990 | 2 | 0.996124 |
| 1990 | 3 | 0.98718 |
| 1990 | 4 | 0.990161 |
| 1990 | 5 | 0.980106 |
| 2000 | 1 | 1 |
| 2000 | 2 | 0.985065 |
| 2000 | 3 | 0.984873 |
| 2000 | 4 | 0.978173 |

And I’m trying to create a line graph which looks like [the output from this stackoverflow question](https://stackoverflow.com/questions/43326784/multiple-line-plots-using-python-bokeh-palettes). I’ve tried this:

> from bokeh.plotting import figure, output\_file, show  
> output\_file(‘index.html’)  
> p = figure(  
> title =‘Simple’)  
> p.line(x= dataset.New\_ID, y= dataset.Peak\_change, legend\_label= ‘Year’)  
> show(p)

But it isn’t being split up into different lines based off `legend_label` in the way circle plots seem to automatically work out. It seems I need a multi line graph, but I don’t understand how to provide the data using the syntax [demonstrated here](https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#multiple-lines). Is it possible to set this up in some kind of for loop?

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 29, 2020, 7:39am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/2 "2020-03-29T07:39:20Z")

</div>

`MultiLine` is a single glyph. If you want each line to have a separate legend item, you will have to use the regular `Line` glyph multiple times:

```python
from io import StringIO

import pandas as pd
from bokeh.plotting import figure, show

df = pd.read_csv(StringIO("""Year	New_ID	Peak_change
1980	1	1
1980	2	0.985478
1980	3	0.974417
1990	1	1
1990	2	0.996124
1990	3	0.98718
1990	4	0.990161
1990	5	0.980106
2000	1	1
2000	2	0.985065
2000	3	0.984873
2000	4	0.978173"""), sep='\t')

p = figure(title='Simple')
for name, group in df.groupby('Year'):
    p.line(x=group.New_ID, y=group.Peak_change, legend_label=str(name))

show(p)

```

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 29, 2020, 9:40am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/3 "2020-03-29T09:40:24Z")

</div>

Thank you!! This works beautifully!

If I could bother you on a slightly different topic, I’m now stuck on trying to assign different colors to the lines but I don’t understand how to integrate that into this for loop… I’ve tried to adapt [the code from this example](https://docs.bokeh.org/en/latest/docs/user_guide/interaction/legends.html#hiding-glyphs):

```
for name, group, i in dataset.groupby('Year'), Spectral11:
    p.line(x=group.New_ID, y=group.Peak_change, legend_label= str(name), color= Spectral11[i])

```

But for reasons probably obvious to you that didn’t work. Any ideas?

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 29, 2020, 9:56am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/4 "2020-03-29T09:56:36Z")

</div>

Given the example that you link (I didn’t check the code):

```auto
for (name, group), color in zip(dataset.groupby('Year'), Spectral11):
    p.line(x=group.New_ID, y=group.Peak_change, legend_label=str(name), color=color)

```

Note that this will display up to 11 lines because `Spectral11` has only 11 colors. If you need more lines, some other palette or coloring scheme should be used.

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 29, 2020, 10:30am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/5 "2020-03-29T10:30:46Z")

</div>

OK great I think that’s nearly there but it didn’t quite work. I’ve tried this, with `Category20`:

for (name, group), color in zip(dataset.groupby(‘Year’), Category20):  
p.line(x=group.New\_ID, y=group.Peak\_change, legend\_label= str(name), color=color)

The error message it throws is `ValueError: expected an element of either Enum('aliceblue', 'antiquewhite', 'aqua', 'aquamarine', ...` going on for maybe 100 colors. I don’t know what Enum means but could it be expecting some kinda string?

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 29, 2020, 12:52pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/6 "2020-03-29T12:52:54Z")

</div>

That’s because `Category20` is not a palette itself, it’s a collection of palettes. Check out its definition in the Bokeh sources.  
You probably want to use `Category20_20`.

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 29, 2020, 2:02pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/7 "2020-03-29T14:02:33Z")

</div>

Ah! Thank you.

Thanks for the help!

---

<div class="post-metadata">

**Author:** ![Carl](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/carl/32/1290_2.png) [@Carl](https://discourse.bokeh.org/u/Carl)\
**Post date:** [March 29, 2020, 3:02pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/8 "2020-03-29T15:02:05Z")

</div>

Hopefully this isn’t straying to far from the path, I too was struggling with this where I wanted to plot multiple columns in a pandas dataframe I had. The dataframe consisted of a Date column (my x-axis value) and Water / Oil columns. The below code is slight variation of what has already been posted above, just wanted to share simple example of what I have working. The main point was to ensure the Date column was in correct datetime format and adding x\_axis\_type=“datetime” to the figure.

```auto

p = figure(sizing_mode="scale_width", plot_height=85,x_axis_type="datetime")

for column_name, spectral_color in zip(['Water','Oil'], Spectral10):
        p.scatter(x=df['Date'], y=df[column_name], size=1.3, color=spectral_color, alpha=0.8, 
                 legend_label=column_name)
```

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 30, 2020, 4:34am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/9 "2020-03-30T04:34:04Z")

</div>

Hey @p-himik might be starting to digress here but tooltips don’t seem to be working, probably because of how we’ve brought in the lines with the for loop and df.groupby. It renders but all the values are ‘???’. I hoped this would work:

```
ttips = HoverTool(tooltips = [
    ("Peak Change", "@{Peak_change}")])
p = figure(title ='whatever')
p.add_tools(ttips)

```

But no dice. I’ve tried to enter tooltips within the for loop but that doesn’t seem to work as `p.line` won’t accept tooltips as an argument.

I’ve had a look around on other posts and stackoverflow but I only found posts that are obsolete or involved workarounds for slightly different things I didn’t understand.

Any ideas?

@Carl cool to see others trying to figure out the same thing!

---

<div class="post-metadata">

**Author:** ![Carl](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/carl/32/1290_2.png) [@Carl](https://discourse.bokeh.org/u/Carl)\
**Post date:** [March 30, 2020, 8:33am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/10 "2020-03-30T08:33:37Z")

</div>

Hi @tvkyq, I think an area to explore is adding the dataframe to bokehs columndatasource

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 30, 2020, 9:12am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/11 "2020-03-30T09:12:41Z")

</div>

Carl is correct. By using `@{Peak_change}` (BTW `{}` are not necessary here, I think), you’re asking the tooltip to look up this value in the data source of the renderer that you hover over. Your renderers don’t have any data source attached since you just provide the data directly.  
Start providing the data via data sources, and make sure they have `Peak_change` column - the tooltip will work then.

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 30, 2020, 9:37am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/12 "2020-03-30T09:37:52Z")

</div>

Ah, not shown in the code I’ve supplied is a line I’ve since added, `source = ColumnDataSource(dataset)`. Perhaps I could’ve better explained how I’m stuck. My issue is that I don’t know to assign `source` to the line renderers.

If I drop `source=source` into the for loop it throws the error message, ‘Expected x and y to reference fields in the supplied data source’, so I’m now unsure what to do.

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 30, 2020, 12:27pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/13 "2020-03-30T12:27:21Z")

</div>

An analog of what you do:

```python
x = [1, 2, 3]
y = [2, 3, 4]
source = ColumnDataSource(data=dict(x=x, y=y))
plot.line(x=x, y=y, source=source)

```

Now compare it what should be done instead:

```auto
source=ColumnDataSource(data=dict(x=[1, 2, 3], y=[2, 3, 4]))
plot.line(x='x', y='y', source=source)

```

Notice how I pass strings that reference columns within the `source` instead of passing the data directly.

If you think the error message could be improved, let us know.

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 30, 2020, 1:21pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/14 "2020-03-30T13:21:32Z")

</div>

Hey @p-himik I’m sorry but I’m kinda new to programming and don’t understand how

```auto
source=ColumnDataSource(data=dict(x=[1, 2, 3], y=[2, 3, 4]))
plot.line(x='x', y='y', source=source)

```

could be applied to the dataframe I’m using that’s thousands of rows long with the `.groupby('Year')` for loop you’ve helped me set up.

Isn’t

```auto
x = [1, 2, 3]
y = [2, 3, 4]
source = ColumnDataSource(data=dict(x=x, y=y))

```

the same as

```auto
source=ColumnDataSource(data=dict(x=[1, 2, 3], y=[2, 3, 4]))

```

this? You’ve just haven’t specified x and y separately, right?

Thanks for being patient with me…

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 30, 2020, 1:58pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/15 "2020-03-30T13:58:08Z")

</div>

Since none of the glyphs share any data, you have to create a separate data source for each glyph. Just put `source = ...` in the loop body and use it:

```python
for (name, group), color in zip(dataset.groupby('Year'), Spectral11):
    source = ColumnDataSource(group)
    p.line(x='New_ID', y='Peak_change', source=source, legend_label=str(name), color=color)

```

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 30, 2020, 9:09pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/16 "2020-03-30T21:09:59Z")

</div>

I’m sorry man but I still can’t get this to work. I’m still getting the same error message as before. I feel like an idiot. Here’s all the relevant code:

```
ttips = HoverTool(tooltips=[
    ("Peak Change", "@Peak_change")])
p = figure(title ='whatever')

for (name, group), color in zip(dataset.groupby('Year'), Category20_20):
    source = ColumnDataSource(group)
    p.line(x=group.New_ID, y=group.Peak_change, legend_label=str(name),
           source=source)

p.add_tools(ttips)

```

Are you sure `source = ColumnDataSource(group)` is correct? Earlier I had it ahead of the for loop as `source = ColunDataSource(dataset)`, as `dataset` is the name of the dataframe. I also tried `source = ColumnDataSource(dataset.groupby(group))` in the for loop but that didn’t work either.

---

<div class="post-metadata">

**Author:** ![p-himik](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/p-himik/32/4010_2.png) [@p-himik](https://discourse.bokeh.org/u/p-himik)\
**Post date:** [March 30, 2020, 9:39pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/17 "2020-03-30T21:39:37Z")

</div>

This is my line:

```python
p.line(x='New_ID', y='Peak_change', source=source, legend_label=str(name), color=color)

```

And this is yours:

```python
p.line(x=group.New_ID, y=group.Peak_change, legend_label=str(name),
       source=source)

```

Apart from the order of the arguments (which doesn’t matter), do you see any difference?

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [March 30, 2020, 10:13pm UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/18 "2020-03-30T22:13:54Z")

</div>

…`x=group.New_ID, y=group.Peak_change `…

[![](https://discourse-uploads.bokeh.org/original/2X/e/e40899cf1f4adcf3b0d38d4e4f0d2ac4d6298959.jpeg) ](https://external-content.duckduckgo.com/iu/?u=https://i1.wp.com/learn.onemonth.com/wp-content/uploads/2017/07/o-EMBARRASSED-facebook.jpg?fit=2000%252C1000&ssl=1&f=1&nofb=1)

---

<div class="post-metadata">

**Author:** ![tvkyq](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/tvkyq/32/1485_2.png) [@tvkyq](https://discourse.bokeh.org/u/tvkyq)\
**Post date:** [May 6, 2020, 1:35am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/19 "2020-05-06T01:35:45Z")

</div>

Hey @p-himik I’m sorry to bring this up again as you’re probably sick of me and I’ve already made enough of a fool of myself. I’m trying to adapt the logic used to create these lines with ColumnDataSource and I can’t figure out where I’m going wrong.

I have a heatmap you might recognize and the values are controlled by a slider, and I’d like this same controlled data to be shown as lines. I think the issue might be caused by `source = ColumnDataSource(column)` - can CDS be supplied with whatever you’re trying to create a group / subset of in this way?

```
from pandas import *
from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import LinearColorMapper, CustomJS, Slider, ColumnDataSource
from bokeh.palettes import Viridis256
from bokeh.plotting import figure

df = DataFrame({'attribute': ['Y', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'Z']
                   , 'period': [1, 2, 3, 4, 1, 2, 3, 4]
                   , '1': [1, 37, 44, 13, 41, 51, 18, 14]
                   , '2': [10, 3, 44, 53, 20, 9, 18, 14]
                   , '3': [80, 37, 22, 13, 13, 44, 18, 14]})

df['period'] = df['period'].astype(str)
periods = df.period.unique().tolist()
attributes = df.attribute.unique().tolist()
selectable_columns = ['1', '2', '3']

source=ColumnDataSource(df)

active = 1
values_select = Slider(title="Values", start=1, end=3, step=1, value=active)
color_mapper = LinearColorMapper(palette=Viridis256, low=df[str(active)].min(), high=df[str(active)].max())
heatmap_fig = figure(x_range=periods, y_range=attributes)
renderer = heatmap_fig.rect(x="period", y="attribute", width=1, height=1, line_color=None, source=source, name=str(active),
                            fill_color={'field': str(active), 'transform': color_mapper})

line_fig = figure()

for column in selectable_columns:
    source = ColumnDataSource(column)
    line_fig.line(x='period'
            , y='attribute'
            , legend_label=str(column)
            , source=source)

values_select.js_on_change('value', CustomJS(args=dict(renderer=renderer, heatmap_fig=heatmap_fig, line_fig=line_fig), code="""\
    const active = cb_obj.value.toString();
    const data = renderer.data_source.data[active];
    renderer.name = active;
    const {transform} = renderer.glyph.fill_color;
    renderer.glyph.fill_color = {field: cb_obj.value, transform: transform};
    heatmap_fig.reset.emit()
    line_fig.reset.emit()
"""))

show(column(values_select, heatmap_fig, line_fig))

```

The error says it expects a dict or pandas.df … but how else could I supply the data?

---

<div class="post-metadata">

**Author:** ![\_jm](https://discourse.bokeh.org/letter_avatar_proxy/v4/letter/_/ac91a4/32.png) [@\_jm](https://discourse.bokeh.org/u/_jm)\
**Post date:** [May 6, 2020, 5:25am UTC](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038/20 "2020-05-06T05:25:04Z")

</div>

Hi @tvkyq

In the for-loop, you are iterating over `selectable_columns` which is a list of integers. The error occurs on the first iteration at first line of that loop because you are attempting to make a ColumnDataSource out of the current iterator value, `'1`'.

```
for column in selectable_columns:
    source = ColumnDataSource(column)

```

Another quick observation is to not reuse the name `column` for your loop variable as it shadows the bokeh `column` model that you’ve imported with the same name.

`from bokeh.layouts import column`

I hope this helps and someone with more context of what you want to actually include in the line plot can answer the actual question you are about.

[Next page](https://discourse.bokeh.org/t/providing-data-for-a-multi-line-from-a-dataframe-having-trouble-figuring-out-how-to-restructure-the-dataframe-use-multi-lines-syntax/5038.md?page=2)
