Generally, changing the color scheme for a plotly express figure is very straight-forward. What's causing the problems here is the fact that species is a categorical variable. Continuous or numerical values are actually easier, but we'll get to that in a bit.

For categorical values, using color_discrete_map is a perfectly valid, albeit cumbersome approach. I prefer using the keyword argument continuous_colorscale in combination with px.colors.qualitative.Antique, where Antique can be changed to any of the discrete color schemes available in plotly express. Just run dir(px.colors.qualitative) to see what are available to you in the plotly version you are running:

['Alphabet',
 'Antique',
 'Bold',
 'D3',
 'Dark2',
 'Dark24',
 'G10',......]

Code 1:

import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length",
                 color="species", color_discrete_sequence=px.colors.qualitative.Antique)

fig.show()

Plot 1:

So what about continuous variables?

Consider the following snippet:

import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length",
                 color="sepal_length", color_continuous_scale=px.colors.sequential.Viridis)

fig.show()

Running this will produce this plot:

You can change the colors to any other theme available under dir(px.colors.sequential), for example color_continuous_scale=px.colors.sequential.Inferno, and get this plot:

What's possibly causing confusion here, is that setting color='species, and keeping color_continuous_scale=px.colors.sequential.Inferno will give you this plot:

The figure now jumps straight back to using the default plotly colors, without giving you any warning about color_continuous_scale=px.colors.sequential.Inferno not having an effect. This is because species is a categorical variable with these different values : ['setosa', 'versicolor', 'virginica'], so color_continuous_scale is simply ignored. For color_continuous_scale to take effect you'll have to use a numerical value, like sepal_length = [5.1, 4.9, 4.7, 4.6, 5. , 5.4, ...]

And this brings us right back to my initial answer for categorical values:

Use the keyword argument continuous_colorscale in combination with px.colors.qualitative

Answer from vestland on Stack Overflow
🌐
Plotly
plotly.com › python › builtin-colorscales
Built-in continuous color scales in Python
A reference for the built-in named continuous (sequential, diverging and cyclical) color scales in Plotly.
🌐
Plotly
plotly.com › python › colorscales
Continuous color scales and color bars in Python
By default, Plotly Express will use the color scale from the active template's layout.colorscales.sequential attribute, and the default active template is plotly which uses the Plasma color scale.
🌐
Plotly
plotly.com › python › discrete-color
Discrete colors in Python
No interpolation occurs when using color sequences, unlike with continuous color scales, and each color is used as-is. Color sequence defaults depend on the layout.colorway attribute of the active template, and can be explicitly specified using the color_discrete_sequence argument for many Plotly Express functions.
🌐
Plotly
plotly.com › python-api-reference › generated › plotly.express.colors.html
plotly.express.colors package — 7.1.0 documentation
Takes a list of colors and scales and constructs a colorscale based on the colors in sequential order. If ‘scale’ is left empty, a linear- interpolated colorscale will be generated. If ‘scale’ is a specified list, it must be the same length as colors and must contain all floats For ...
🌐
GeeksforGeeks
geeksforgeeks.org › python › built-in-continuous-color-scales-in-python-plotly
Built-in Continuous Color Scales in Python Plotly - GeeksforGeeks
July 23, 2025 - Code to view the built-in sequential color scales in plotly.colors.sequential module. Swatches_sequential() method is used to view the color scales.
🌐
Plotly
plotly.com › python-api-reference › generated › plotly.colors.html
plotly.colors package — 7.1.0 documentation
Takes a list of colors and scales and constructs a colorscale based on the colors in sequential order. If ‘scale’ is left empty, a linear- interpolated colorscale will be generated. If ‘scale’ is a specified list, it must be the same length as colors and must contain all floats For ...
Top answer
1 of 2
35

Generally, changing the color scheme for a plotly express figure is very straight-forward. What's causing the problems here is the fact that species is a categorical variable. Continuous or numerical values are actually easier, but we'll get to that in a bit.

For categorical values, using color_discrete_map is a perfectly valid, albeit cumbersome approach. I prefer using the keyword argument continuous_colorscale in combination with px.colors.qualitative.Antique, where Antique can be changed to any of the discrete color schemes available in plotly express. Just run dir(px.colors.qualitative) to see what are available to you in the plotly version you are running:

['Alphabet',
 'Antique',
 'Bold',
 'D3',
 'Dark2',
 'Dark24',
 'G10',......]

Code 1:

import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length",
                 color="species", color_discrete_sequence=px.colors.qualitative.Antique)

fig.show()

Plot 1:

So what about continuous variables?

Consider the following snippet:

import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length",
                 color="sepal_length", color_continuous_scale=px.colors.sequential.Viridis)

fig.show()

Running this will produce this plot:

You can change the colors to any other theme available under dir(px.colors.sequential), for example color_continuous_scale=px.colors.sequential.Inferno, and get this plot:

What's possibly causing confusion here, is that setting color='species, and keeping color_continuous_scale=px.colors.sequential.Inferno will give you this plot:

The figure now jumps straight back to using the default plotly colors, without giving you any warning about color_continuous_scale=px.colors.sequential.Inferno not having an effect. This is because species is a categorical variable with these different values : ['setosa', 'versicolor', 'virginica'], so color_continuous_scale is simply ignored. For color_continuous_scale to take effect you'll have to use a numerical value, like sepal_length = [5.1, 4.9, 4.7, 4.6, 5. , 5.4, ...]

And this brings us right back to my initial answer for categorical values:

Use the keyword argument continuous_colorscale in combination with px.colors.qualitative

2 of 2
20

You can use a method called color_discrete_map, which is a dict of k,v pairs where the k is the value for the color and v is the colorscheme. For example:

fig = px.scatter(df, x='sepal_length', y='sepal_width',
              color='species', color_discrete_map={'setosa': 'lightcyan', 
                                                   'versicolor': 'royalblue', 'virginica': 'darkblue'})

🌐
Plotly
community.plotly.com › 📊 plotly python
How can I iterate over plotly color scale? - 📊 Plotly Python - Plotly Community Forum
July 17, 2023 - I want to iterate over a plotly color scale so I can create a list of colors to apply to each of my 22 line graphs. I’m plotting this using Streamlit. This is my code below: import plotly.express as px import streamlit as st cmap = px.colors.sequential.Viridis color_scale = [cmap[i % 256] for i in range(22)] fig = px.line(df, x='Month', y='Sum', color='group', color_discrete_sequence=color_scale) fig.update_layout( title='Sum of ', xaxis_title='Month', yaxis_title='Views ove...
Find elsewhere
🌐
Plotly
plotly.com › r › builtin-colorscales
Built-in continuous color scales in R
A reference for the built-in named continuous (sequential, diverging and cyclical) color scales in Plotly.
🌐
Plotly
community.plotly.com › 📊 plotly python
Choose color inside plotly.colors.sequential - 📊 Plotly Python - Plotly Community Forum
January 8, 2022 - I would like to make a graph with px and pick only a part of a plotly.colors.sequential colors. let say for example, that i want to use : Blackbody. but not entirely, just from 0.2 to 0.50 ( because you can select this if you click and drag on this color → Builtin Colorscales) how do you ...
🌐
Statistics Globe
statisticsglobe.com › home › learn r programming (tutorial & examples) | free introduction › change colors of plotly graph in r (example)
Change Colors of plotly Graph in R (Example) | Modify XY-Plot & Barplot
November 22, 2021 - plot_ly( data = df, x = ~perchsd, ... "#c10dd1") ) Sequential palettes use different shades of one or two colors to create a smooth gradient to represent changes in magnitude....
🌐
Plotly
plotly.github.io › plotly.py-docs › generated › plotly.colors.html
plotly.colors package — 6.8.0 documentation
Takes a list of colors and scales and constructs a colorscale based on the colors in sequential order. If ‘scale’ is left empty, a linear- interpolated colorscale will be generated. If ‘scale’ is a specified list, it must be the same length as colors and must contain all floats For ...
Top answer
1 of 3
5

You can achieve this using only 2 more parameters in px.line:

  • markers=True
  • color_discrete_sequence=my_plotly_continuous_sequence

The complete code would look something like this (Note the list slicing [::4] so that the colors are well spaced):

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

x = [1, 2, 3, 4, 5, 6]

df = pd.DataFrame(
    {
        'x': x * 3,
        'y': list(np.array(x)) + list(np.array(x) ** 2) + list(np.array(x) ** .5),
        'color': list(np.array(x) * 0) + list(np.array(x) * 0 + 1) + list(np.array(x) * 0 + 2),
    }
)

fig = px.line(
    df,
    x='x',
    y='y',
    color='color',
    color_discrete_sequence=px.colors.sequential.Plasma[::4],
    markers=True,
    template='plotly'
)
fig.show()

This produces the following output.

In case you have more lines than the colors present in the colormap, you can construct a custom colorscale so that you get one complete sequence instead of a cycling sequence:

rgb = px.colors.convert_colors_to_same_type(px.colors.sequential.RdBu)[0]

colorscale = []
n_steps = 4  # Control the number of colors in the final colorscale
for i in range(len(rgb) - 1):
    for step in np.linspace(0, 1, n_steps):
        colorscale.append(px.colors.find_intermediate_color(rgb[i], rgb[i + 1], step, colortype='rgb'))

fig = px.line(df_e, x='temperature', y='probability', color='year', color_discrete_sequence=colorscale, height=900)
fig.show()

2 of 3
4

I am not sure this is possible using only plotly.express. If you use px.line, then you can pass the argument markers=True as described in this answer, but from the px.line documentation it doesn't look like continuous color scales are supported.

UPDATED ANSWER: in order to have both a legend that groups both the lines and markers together, it's probably simpest to use go.Scatter with the argument mode='lines+markers'. You'll need to add the traces one at a time (by plotting each unique color portion of the data one at a time) in order to be able to control each line+marker group from the legend.

When plotting these traces, you will need some functions to retrieve the colors of the lines from the continuous color scale because go.Scatter won't know what color your lines are supposed to be unless you specify them - thankfully that has been answered here.

Also you won't be able to generate a colorbar adding the markers one color at a time, so to add a colorbar, you can plot all of the markers at once using go.Scatter, but use the argument marker=dict(size=0, color="rgba(0,0,0,0)", colorscale='Plasma', colorbar=dict(thickness=20)) to display a colorbar, but ensure that these duplicate markers are not visible.

Putting all of this together:

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

x = [1,2,3,4,5,6]

df = pd.DataFrame(
    {
        'x': x*3,
        'y': list(np.array(x)) + list(np.array(x)**2) + list(np.array(x)**.5),
        'color': list(np.array(x)*0) + list(np.array(x)*0+1) + list(np.array(x)*0+2),
    }
)

# This function allows you to retrieve colors from a continuous color scale
# by providing the name of the color scale, and the normalized location between 0 and 1
# Reference: https://stackoverflow.com/questions/62710057/access-color-from-plotly-color-scale

def get_color(colorscale_name, loc):
    from _plotly_utils.basevalidators import ColorscaleValidator
    # first parameter: Name of the property being validated
    # second parameter: a string, doesn't really matter in our use case
    cv = ColorscaleValidator("colorscale", "")
    # colorscale will be a list of lists: [[loc1, "rgb1"], [loc2, "rgb2"], ...] 
    colorscale = cv.validate_coerce(colorscale_name)
    
    if hasattr(loc, "__iter__"):
        return [get_continuous_color(colorscale, x) for x in loc]
    return get_continuous_color(colorscale, loc)
        

# Identical to Adam's answer
import plotly.colors
from PIL import ImageColor

def get_continuous_color(colorscale, intermed):
    """
    Plotly continuous colorscales assign colors to the range [0, 1]. This function computes the intermediate
    color for any value in that range.

    Plotly doesn't make the colorscales directly accessible in a common format.
    Some are ready to use:
    
        colorscale = plotly.colors.PLOTLY_SCALES["Greens"]

    Others are just swatches that need to be constructed into a colorscale:

        viridis_colors, scale = plotly.colors.convert_colors_to_same_type(plotly.colors.sequential.Viridis)
        colorscale = plotly.colors.make_colorscale(viridis_colors, scale=scale)

    :param colorscale: A plotly continuous colorscale defined with RGB string colors.
    :param intermed: value in the range [0, 1]
    :return: color in rgb string format
    :rtype: str
    """
    if len(colorscale) < 1:
        raise ValueError("colorscale must have at least one color")

    hex_to_rgb = lambda c: "rgb" + str(ImageColor.getcolor(c, "RGB"))

    if intermed <= 0 or len(colorscale) == 1:
        c = colorscale[0][1]
        return c if c[0] != "#" else hex_to_rgb(c)
    if intermed >= 1:
        c = colorscale[-1][1]
        return c if c[0] != "#" else hex_to_rgb(c)

    for cutoff, color in colorscale:
        if intermed > cutoff:
            low_cutoff, low_color = cutoff, color
        else:
            high_cutoff, high_color = cutoff, color
            break

    if (low_color[0] == "#") or (high_color[0] == "#"):
        # some color scale names (such as cividis) returns:
        # [[loc1, "hex1"], [loc2, "hex2"], ...]
        low_color = hex_to_rgb(low_color)
        high_color = hex_to_rgb(high_color)

    return plotly.colors.find_intermediate_color(
        lowcolor=low_color,
        highcolor=high_color,
        intermed=((intermed - low_cutoff) / (high_cutoff - low_cutoff)),
        colortype="rgb",
    )

fig = go.Figure()

## add the lines+markers
for color_val in df.color.unique():
    color_val_normalized = (color_val - min(df.color)) / (max(df.color) - min(df.color))
    # print(f"color_val={color_val}, color_val_normalized={color_val_normalized}")
    df_subset = df[df['color'] == color_val]
    fig.add_trace(go.Scatter(
        x=df_subset['x'],
        y=df_subset['y'],
        mode='lines+markers',
        marker=dict(color=get_color('Plasma', color_val_normalized)),
        name=f"line+marker {color_val}",
        legendgroup=f"line+marker {color_val}"
    ))

## add invisible markers to display the colorbar without displaying the markers
fig.add_trace(go.Scatter(
    x=df['x'],
    y=df['y'],
    mode='markers',
    marker=dict(
        size=0, 
        color="rgba(0,0,0,0)", 
        colorscale='Plasma', 
        cmin=min(df.color),
        cmax=max(df.color),
        colorbar=dict(thickness=40)
    ),
    showlegend=False
))

fig.update_layout(
    legend=dict(
    yanchor="top",
    y=0.99,
    xanchor="left",
    x=0.01),
    yaxis_range=[min(df.y)-2,max(df.y)+2]
)

fig.show()

Top answer
1 of 1
2

You should add new plots to the first one, I have a small number of samples to plot, you can play with other configurations as you want:

import plotly.express as px
import plotly.graph_objects as go
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import geopandas as gpd
from openpyxl import load_workbook
import numpy as np
import pandas as pd
from io import StringIO

import numpy as np; 
np.random.seed(0)
import seaborn as sns;




data = '''
x   y   Base_TT
14.1315559  55.75811117 1.871884861
14.66228957 57.02751992 1.599971112
14.49407157 56.06563489 1.307165278
13.21996788 55.4786748  1.411554445
14.00501286 55.72120854 1.968138334
12.73736102 56.71097302 1.309849028
14.56668525 56.74872925 1.719116945
13.24138764 56.41359089 2.000620417
14.94308088 56.54283706 1.668724723
14.5744739  56.05695327 1.266861528
'''

df_centroid_Coord = pd.read_csv(StringIO(data), delim_whitespace=True)


data = '''
ID "Ambulance station name" Longtitude Latitude
0 1 AImhult 14.128734 56.547992
1 2 Angelhdm 12.870739 56.242114
2 3 Alvesta 14.549503 56.920740
3 4 "Ostra Ljungby" 13.057450 56.188099
4 5 Broby 14.080958 56.254481
5 6 Bromölla 14.466869 56.072272
6 7 Försláv 12.814913 56.350098
7 9 Hasslehdm 13.778234 56.161536
8 10 Haganas 12.556995 56.206016
9 11 Hörby 13.643265 55.849811
10 12 "Halmstad.Vaster" 12.819960 56.674306 
'''

df_station = pd.read_csv(StringIO(data), delim_whitespace=True) 
df_station.rename(columns={'Longtitude':'x', 'Latitude':'y'}, inplace=True)
df_centroid_Coord['Ambulance_Treatment_Time'] = df_centroid_Coord ['Base_TT']

fig = px.scatter(df_centroid_Coord, x="x", y="y", 
                 title="Southern Region Centroids", 
                 color='Ambulance_Treatment_Time', 
                 log_x=True,
                 size_max=60, 
                 color_continuous_scale='Reds',
                 range_color=(0.5,2),
                 )

fig.update_traces(marker={'size': 4, 'symbol': 1})
fig.add_trace(go.Scatter(x=df_station['x'],
                         y=df_station['y'],
                         mode='markers+text',
                         text=df_station['Ambulance station name'],
                         textposition='top center',
                         showlegend=True,
                         marker=dict(
                             size=8,
                             symbol=2,
                             color='black'
                         )
                        )
             )



fig.show()

🌐
Plotly
community.plotly.com › 📊 plotly python
From PX to GO : from color_discrete_sequence to marker_colors - 📊 Plotly Python - Plotly Community Forum
August 11, 2023 - Hi there, Here is an example of ... import plotly.express as px df = px.data.tips() fig = px.pie(df, values='tip', names='day', color_discrete_sequence=px.colors.sequential.RdBu) fig.show() And I wanted to switch ...
🌐
Improve & Repeat
improveandrepeat.com › 2023 › 09 › python-friday-193-choosing-colours-for-plotly
#193: Choosing Colours for Plotly - Python Friday
September 22, 2023 - We can use the names of those sequences in our plots with the color_discrete_sequence parameter:
🌐
Plotly
plotly.com › r › discrete-color
Discrete colors in R
How to use and configure discrete color sequences, also known as categorical or qualitative color scales in R. Plotly Studio: Transform any dataset into an interactive data application in minutes with AI.
🌐
GeeksforGeeks
geeksforgeeks.org › python-plotly-how-to-set-up-a-color-palette
Python Plotly - How to set up a color palette? - GeeksforGeeks
April 15, 2025 - Brighter colors (yellow to red) indicate lower light levels, while darker (green to purple) shows higher intensity · px. bar() method is used to plot a barplot of the data we provide. The list of colours is passed to the color_discrete_sequence parameter of the px.bar() method.
🌐
GitHub
github.com › llovo-code › plotly › blob › master › plotly › colors.py
plotly/plotly/colors.py at master · llovo-code/plotly
raise exceptions.PlotlyError( "'scale' must be a list that contains a strictly increasing " "sequence of numbers." ) · · def make_colorscale(colors, scale=None): """ Makes a colorscale from a list of colors and a scale · · Takes a list of colors and scales and constructs a colorscale based · on the colors in sequential order.
Author: llovo-code