简体   繁体   中英

Plotly: How to using shifting colors for different traces?

I'm plotting graphs in plotly using data from pandas. I have a dictionary where the key is a date eg 2020-10-26 , and the value is a pd.Dataframe , which has a time column and 2 data columns.

Example of data in.csv format:

datetime,SeriesA,SeriesB
2020-10-23 06:00:03.560996+01:00,0,0
2020-10-23 06:05:03.358855+01:00,0,0
2020-10-23 06:10:02.927629+01:00,0,0
2020-10-23 06:15:02.514076+01:00,0,0
2020-10-23 06:20:03.231765+01:00,0,0
2020-10-23 06:25:02.790677+01:00,0,0
2020-10-23 06:30:04.252621+01:00,0,0
2020-10-23 06:35:02.845816+01:00,0,0
2020-10-23 06:40:03.510711+01:00,0,0
2020-10-23 06:45:03.235390+01:00,0,0
2020-10-23 06:50:02.689276+01:00,0,0
2020-10-23 06:55:03.569083+01:00,0,0
2020-10-23 07:00:08.279973+01:00,0,0
2020-10-23 07:05:02.816612+01:00,0,0
2020-10-23 07:10:03.417112+01:00,2,0
2020-10-23 07:15:03.041706+01:00,2,0
2020-10-23 07:20:02.537567+01:00,3,0
2020-10-23 07:25:03.266320+01:00,5,0
2020-10-23 07:30:02.900625+01:00,5,0
2020-10-23 07:35:03.577497+01:00,5,0
2020-10-23 07:40:03.179229+01:00,7,0
2020-10-23 07:45:02.743349+01:00,10,0
2020-10-23 07:50:03.285283+01:00,11,0
2020-10-23 07:55:02.858642+01:00,11,0
2020-10-23 08:00:03.641784+01:00,10,0
2020-10-23 08:05:03.256219+01:00,10,0
2020-10-23 08:10:02.994154+01:00,9,0
2020-10-23 08:15:02.525091+01:00,9,0
2020-10-23 08:20:03.261529+01:00,9,0
2020-10-23 08:25:02.890515+01:00,9,0
2020-10-23 08:30:03.533912+01:00,9,0
2020-10-23 08:35:03.206510+01:00,7,0
2020-10-23 08:40:02.719998+01:00,7,0
2020-10-23 08:45:03.310976+01:00,7,0
2020-10-23 08:50:02.996382+01:00,4,0
2020-10-23 08:55:02.697139+01:00,7,0
2020-10-23 09:00:03.721763+01:00,7,0
2020-10-23 09:05:03.182091+01:00,7,0
2020-10-23 09:10:02.765971+01:00,8,0
2020-10-23 09:15:03.360654+01:00,8,0
2020-10-23 09:20:02.990297+01:00,10,0
2020-10-23 09:25:02.661501+01:00,11,0
2020-10-23 09:30:03.275004+01:00,14,0
2020-10-23 09:35:02.868574+01:00,14,0
2020-10-23 09:40:03.460406+01:00,15,0
2020-10-23 09:45:02.905538+01:00,18,0
2020-10-23 09:50:02.423377+01:00,20,0
2020-10-23 09:55:02.984470+01:00,24,0
2020-10-23 10:00:02.622322+01:00,24,0
2020-10-23 10:05:03.166971+01:00,26,0
2020-10-23 10:10:02.859788+01:00,27,0
2020-10-23 10:15:03.494884+01:00,27,0
2020-10-23 10:20:03.113251+01:00,28,0
2020-10-23 10:25:02.606379+01:00,29,0
2020-10-23 10:30:03.268436+01:00,30,0
2020-10-23 10:35:02.889803+01:00,35,0
2020-10-23 10:40:03.577297+01:00,37,0
2020-10-23 10:45:03.082449+01:00,37,0
2020-10-23 10:50:02.680122+01:00,37,0
2020-10-23 10:55:03.207217+01:00,40,0
2020-10-23 11:00:03.633144+01:00,40,0
2020-10-23 11:05:03.342871+01:00,39,0
2020-10-23 11:10:02.952711+01:00,40,0
2020-10-23 11:15:02.519122+01:00,42,0
2020-10-23 11:20:03.330055+01:00,42,0
2020-10-23 11:25:02.948754+01:00,44,0
2020-10-23 11:30:02.505908+01:00,43,0
2020-10-23 11:35:03.091022+01:00,42,0
2020-10-23 11:40:02.570567+01:00,38,0
2020-10-23 11:45:03.214173+01:00,38,0
2020-10-23 11:50:02.909830+01:00,38,0
2020-10-23 11:55:02.493098+01:00,40,4
2020-10-23 12:00:03.200475+01:00,41,5
2020-10-23 12:05:02.851384+01:00,45,6
2020-10-23 12:10:03.545193+01:00,45,7
2020-10-23 12:15:03.191269+01:00,42,8
2020-10-23 12:20:02.726863+01:00,45,9
2020-10-23 12:25:03.444214+01:00,47,9
2020-10-23 12:30:03.266972+01:00,49,9
2020-10-23 12:35:02.904323+01:00,53,9
2020-10-23 12:40:03.548200+01:00,53,10
2020-10-23 12:45:03.065578+01:00,49,10
2020-10-23 12:50:02.517495+01:00,49,10
2020-10-23 12:55:03.228082+01:00,48,10
2020-10-23 13:00:03.344813+01:00,53,12
2020-10-23 13:05:02.999236+01:00,54,12
2020-10-23 13:10:02.555469+01:00,54,14
2020-10-23 13:15:03.424480+01:00,62,14
2020-10-23 13:20:03.178713+01:00,62,14
2020-10-23 13:25:02.856786+01:00,64,14
2020-10-23 13:30:03.538784+01:00,66,17
2020-10-23 13:35:03.226000+01:00,65,17
2020-10-23 13:40:02.738893+01:00,65,20
2020-10-23 13:45:03.216859+01:00,68,20
2020-10-23 13:50:02.801997+01:00,71,22
2020-10-23 13:55:03.325790+01:00,73,22
2020-10-23 14:00:03.032139+01:00,76,24
2020-10-23 14:05:02.713786+01:00,77,23
2020-10-23 14:10:03.329970+01:00,84,23
2020-10-23 14:15:02.891348+01:00,81,23
2020-10-23 14:20:02.587012+01:00,84,23
2020-10-23 14:25:03.119747+01:00,82,25
2020-10-23 14:30:03.751337+01:00,82,25
2020-10-23 14:35:03.332507+01:00,88,23
2020-10-23 14:40:03.049341+01:00,85,23
2020-10-23 14:45:02.630885+01:00,85,20
2020-10-23 14:50:03.287446+01:00,86,19
2020-10-23 14:55:02.915400+01:00,86,18
2020-10-23 15:00:07.137616+01:00,85,16
2020-10-23 15:05:02.683116+01:00,82,14
2020-10-23 15:10:03.373464+01:00,85,14
2020-10-23 15:15:03.128489+01:00,88,14
2020-10-23 15:20:02.846043+01:00,86,14
2020-10-23 15:25:03.462925+01:00,87,15
2020-10-23 15:30:03.131532+01:00,92,15
2020-10-23 15:35:02.721796+01:00,97,15
2020-10-23 15:40:03.375007+01:00,102,15
2020-10-23 15:45:03.020813+01:00,101,15
2020-10-23 15:50:02.563966+01:00,91,15
2020-10-23 15:55:03.235962+01:00,89,15
2020-10-23 16:00:03.040490+01:00,87,19
2020-10-23 16:05:02.467856+01:00,90,19
2020-10-23 16:10:03.099486+01:00,92,19
2020-10-23 16:15:02.637764+01:00,94,18
2020-10-23 16:20:03.153888+01:00,94,18
2020-10-23 16:25:02.736936+01:00,91,18
2020-10-23 16:30:03.359875+01:00,93,17
2020-10-23 16:35:02.974661+01:00,90,19
2020-10-23 16:40:02.513056+01:00,91,19
2020-10-23 16:45:03.092756+01:00,92,20
2020-10-23 16:50:02.659552+01:00,96,21
2020-10-23 16:55:03.478308+01:00,96,21
2020-10-23 17:00:04.117017+01:00,91,24
2020-10-23 17:05:02.685190+01:00,95,24
2020-10-23 17:10:03.267694+01:00,96,24
2020-10-23 17:15:03.019771+01:00,101,26
2020-10-23 17:20:02.526978+01:00,105,31
2020-10-23 17:25:03.206001+01:00,106,33
2020-10-23 17:30:02.865237+01:00,106,35
2020-10-23 17:35:03.366034+01:00,107,40
2020-10-23 17:40:02.992485+01:00,114,42
2020-10-23 17:45:02.552713+01:00,108,44
2020-10-23 17:50:03.218854+01:00,116,43
2020-10-23 17:55:02.755765+01:00,112,45
2020-10-23 18:00:03.442851+01:00,112,46
2020-10-23 18:05:03.125732+01:00,113,43
2020-10-23 18:10:02.650996+01:00,113,42
2020-10-23 18:15:03.224235+01:00,115,42
2020-10-23 18:20:02.852754+01:00,114,44
2020-10-23 18:25:03.375879+01:00,110,45
2020-10-23 18:30:03.504858+01:00,110,42
2020-10-23 18:35:03.023102+01:00,107,40
2020-10-23 18:40:02.560902+01:00,103,37
2020-10-23 18:45:03.183863+01:00,101,37
2020-10-23 18:50:02.776229+01:00,102,40
2020-10-23 18:55:03.366546+01:00,99,40
2020-10-23 19:00:05.100330+01:00,94,40
2020-10-23 19:05:02.577656+01:00,93,41
2020-10-23 19:10:03.234291+01:00,93,45
2020-10-23 19:15:02.765871+01:00,89,45
2020-10-23 19:20:03.269868+01:00,92,45
2020-10-23 19:25:02.891858+01:00,89,43
2020-10-23 19:30:03.859379+01:00,86,43
2020-10-23 19:35:03.410564+01:00,89,42
2020-10-23 19:40:03.126319+01:00,85,39
2020-10-23 19:45:02.686578+01:00,82,38
2020-10-23 19:50:03.409481+01:00,80,34
2020-10-23 19:55:03.000850+01:00,78,34
2020-10-23 20:00:04.680330+01:00,81,32
2020-10-23 20:05:03.269432+01:00,81,32
2020-10-23 20:10:02.847406+01:00,83,33
2020-10-23 20:15:03.422214+01:00,79,34
2020-10-23 20:20:03.025468+01:00,78,33
2020-10-23 20:25:02.639656+01:00,75,31
2020-10-23 20:30:03.241510+01:00,71,31
2020-10-23 20:35:02.787490+01:00,66,31
2020-10-23 20:40:03.433893+01:00,65,28
2020-10-23 20:45:03.029779+01:00,67,20
2020-10-23 20:50:02.478445+01:00,63,19
2020-10-23 20:55:03.064874+01:00,63,19
2020-10-23 21:00:11.388007+01:00,59,16
2020-10-23 21:05:02.915554+01:00,59,16
2020-10-23 21:10:02.508213+01:00,54,16
2020-10-23 21:15:03.024323+01:00,53,16
2020-10-23 21:20:02.577168+01:00,51,16
2020-10-23 21:25:03.403608+01:00,50,13
2020-10-23 21:30:03.193242+01:00,47,13
2020-10-23 21:35:03.329020+01:00,47,10
2020-10-23 21:40:02.906741+01:00,45,10
2020-10-23 21:45:02.359574+01:00,38,10
2020-10-23 21:50:03.115074+01:00,37,10
2020-10-23 21:55:02.770450+01:00,34,10
2020-10-23 22:00:03.658104+01:00,34,10
2020-10-23 22:05:03.182939+01:00,34,10
2020-10-23 22:10:02.834897+01:00,34,10
2020-10-23 22:15:03.545781+01:00,33,10
2020-10-23 22:20:03.130197+01:00,31,10
2020-10-23 22:25:02.644800+01:00,31,10
2020-10-23 22:30:03.311895+01:00,30,10
2020-10-23 22:35:02.958333+01:00,30,10
2020-10-23 22:40:02.527824+01:00,30,9
2020-10-23 22:45:03.243267+01:00,29,9
2020-10-23 22:50:02.808424+01:00,25,9
2020-10-23 22:55:03.338346+01:00,24,9
for day, df in data.items():
    day_name = datetime.datetime.strptime(day, "%Y-%m-%d").strftime("%A") # convert str to datetime, then to day
    traces.append(go.Scatter(x=df["time"], y=df["SeriesA"], name=f"{day_name} SeriesA"))
    traces.append(go.Scatter(x=df["time"], y=df["SeriesB"], name=f"{day_name} SeriesB"))

Is there any way to plot each line as a different colour from a gradually shifting colour scale? Ideally I'd like all traces from Mondays to be a different shade of red, and every trace from Tuesdays to be say, a different shade of yellow.

The only way I can think to do this is manually enter hex values into a list, and then have an index for each day of the week. Then when plotting the trace do:

# If statement for every day of the week
if day_name == "Monday":
    color = red_hex_values[monday_idx]
    monday_idx += 1

traces.append(go.Scatter(x=df["time"], y=df["SeriesA"], name=f"{day_name} SeriesA", color=color))

This seems like a very messy way to do this though.

Intro

Your question could make use of a bit better focus, in that it is really two questions:

  1. How to make a custom color scale
  2. How to use shifting colors for weekdays in plotly.

I've taken the liberty to focus more or less exclusively on the latter part. Although I'll briefly cover some options for the former - which we can come back to later if you'd like.

Answer

This is an interesting question, and I think I've found a viable solution through a cyclical iteration of specified color scales stored as values in a dictionary daymap where the keys are weekday names:

daymap = {'Monday':cycle(px.colors.sequential.Reds),
           'Tuesday':cycle(px.colors.sequential.Greens),
         }

px.colors.sequential.Reds and px.colors.sequential.Greens are built-in plotly color scales . You specifically asked for yellow. But this will have to do for now.

I've set it up so that any defined weekday, color scale pair you set up is assigned in the plot, and all weekday names that you opt not to define is given a single custom color specified by you using a custom function colfx() :

def colfx(daymap, day_name, default_color):
    if day_name in daymap.keys():
        return next(daymap[day_name])
    else:
        return default_color

The complete code snippet below with a random data sample for 60 days will produce the Plot 1 below using, among a few other details, the specifications mentioned above.

Plot 1

在此处输入图像描述

Plot 2 is produced by adding another key, value pair in daymap and changing the default color in colfx() to 'rgba(150,150,150, 0.2)' . I've found it practical to use rgba colors for the default color since the last term 0.2 will let you easily set the opacity of the color.

Plot 2

在此处输入图像描述

Complete code

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

# data
obs = 60
dates = pd.date_range(start='2020-01-01', periods=obs)
random = np.random.RandomState(0)
df = pd.DataFrame({'data': np.random.uniform(low=0, high=100, size=obs).tolist()}, index=dates)

# custom function to assign next color in a color sequence
# for each new day defined in the dict daymap
def colfx(daymap, day_name, default_color):
    if day_name in daymap.keys():
        return next(daymap[day_name])
    else:
        return default_color

# color specifications for weekday
daymap = {'Monday':cycle(px.colors.sequential.Reds),
           'Tuesday':cycle(px.colors.sequential.Greens),
           'Friday':cycle(px.colors.sequential.thermal)
         }
    
# container for weekday names added to the figure legend
# if the weekday names has ALREADY been added to the legend,
# then no further additions are made
fignames = []

fig=go.Figure()
for row in df.iterrows():
    day_name=row[0].strftime("%A")
    fignames = [d.name for d in fig.data]
    fig.add_bar(x=[row[0]],
                y=[row[1]['data']],
                marker_color=colfx(daymap=daymap, day_name = day_name, default_color='rgba(150,150,150, 0.2)'),
                name=day_name,
                legendgroup = day_name,
                showlegend = False if day_name in fignames else True
               )
    
fig.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM