2

I have a dataFrame for example:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame(data = [{'key': '1', 'value': '1', 'metadata': '3'}, {'key': '2', 'value': '2', 'metadata': '3'}, {'key': '1', 'value': '3', 'metadata': '3'}, {'key': '2', 'value': '4', 'metadata':
   ...: '3'}])

In [3]: df
Out[3]: 
  key value metadata
0   1     1        3
1   2     2        3
2   1     3        3
3   2     4        3

I want to split the df by the "key", i.e.

In [4]: df_list = [d for _, d in df.groupby(['key'])]

In [5]: df_list
Out[5]: 
[  key value metadata
 0   1     1        3
 2   1     3        3,
   key value metadata
 1   2     2        3
 3   2     4        3]

Now I have list of N (2) dataFrames based on number of unique keys. How can I plot this using plotly?

I can

In [6]: import plotly.express as px

In [7]: fig = px.line(df_list[0])

but how can I add the other lines? plotly.express.Figure has no add_line method...

CIsForCookies
  • 12,097
  • 11
  • 59
  • 124

1 Answers1

4

Running plotly.express wil return a plotly.graph_objs._figure.Figure object. The same goes for plotly.graph_objects with go.Figure(). So after building a figure using plotly express, you can add lines or traces using:

fig.add_trace(go.Scatter)

Or:

fig.add_scatter()

Other options are:

fig.add_area()
fig.add_bar()

After building a fig you can run dir(fig) to learn more.

So in a dataframe such as this:

   2021  2022  2023
0     0     0     0
1     0    -1    -2
2    -1    -1    -3
3    -1    -2    -2
4    -1    -1    -3

You can add line / trace to an existing figure using:

fig.add_trace(go.Scatter(x = df.index, y = df['2023']))

If you prefer to keep control of subsets of your data through dictionaries, one approach to add several traces is this:

extra = {'2024': df['2024'],
         '2025': df['2025']}

for k, v in extra.items():
    fig.add_scatter(x=v.index, y = v, name = k + ' from dict' )

enter image description here

Complete code:

import pandas as pd
import numpy as np
import plotly
import plotly.express as px
import plotly.graph_objects as go

# data
np.random.seed(1)
start = 2021
ncols = 6
nrows = 1000
cols = [str(i) for i in np.arange(start, start+ncols)]
df = pd.DataFrame(np.random.randint(-1,2, (nrows,ncols)), columns = cols).cumsum()
df.iloc[0] = 0

# figure
fig = px.line(df, x=df.index, y=cols[:-4])
fig.update_layout(template = 'plotly_dark')

# fig.add_trace(go.Scatter(x = df.index, y = df['2023'], name = '2023 = added trace'))

fig.add_scatter(x = df.index, y = df['2023'], name = '2023 from add_trace')


extra = {'2024': df['2024'],
         '2025': df['2025']}

for k, v in extra.items():
    fig.add_scatter(x=v.index, y = v, name = k + ' from dict' )

fig.show()
vestland
  • 55,229
  • 37
  • 187
  • 305
  • Your answer seems really great, but I think I had asked the wrong question... This is my csv: Device,Name,Stable Temperature (C),metadata 01:00.0,a,40,foo 03:00.0,a,42,foo 01:00.0,b,38,foo 03:00.0,b,44,foo 01:00.0,c,41,foo 03:00.0,c,42,foo 01:00.0,d,20,foo 03:00.0,d,28,foo And I want to plot it so that variable=device, x=name, y=temperature, and the metadata is a hover - I can't make your answer stick in this situation – CIsForCookies Feb 15 '21 at 13:01
  • 1
    @CIsForCookies Include a sample of your data as described [here](https://stackoverflow.com/questions/63163251/pandas-how-to-easily-share-a-sample-dataframe-using-df-to-dict/63163254#63163254), and I'm sure we can make it stick. – vestland Feb 15 '21 at 13:04
  • {'Device': {0: '01:00.0', 1: '03:00.0', 2: '01:00.0', 3: '03:00.0', 4: '01:00.0', 5: '03:00.0', 6: '01:00.0', 7: '03:00.0'}, 'Name': {0: 'a', 1: 'a', 2: 'b', 3: 'b', 4: 'c', 5: 'c', 6: 'd', 7: 'd'}, 'Stable Temperature (C)': {0: 40, 1: 42, 2: 38, 3: 44, 4: 41, 5: 42, 6: 20, 7: 28}, 'metadata': {0: 'foo', 1: 'foo', 2: 'foo', 3: 'foo', 4: 'foo', 5: 'foo', 6: 'foo', 7: 'foo'}} – CIsForCookies Feb 15 '21 at 13:12
  • btw, I'm looking into `pd.melt` - as I think it will give a concise solution. No success yet.. – CIsForCookies Feb 15 '21 at 13:19