使跟踪颜色在 Figures/Graphs 中保持一致

Making Trace Colors Consistency Across Figures/Graphs

假设我有以下代码:

import pandas as pd
import numpy as np
import plotly.express as px
from dash.dependencies import Output, Input
from dash import dcc
from dash import html
import dash


df_a = pd.DataFrame({"time":pd.Series(pd.date_range("1-nov-2021","2-nov-2021", freq="S")).sample(30),
             "bacteria_count":np.random.randint(0,500, 30), "bacteria_type":np.random.choice(list("AB"),30)})

df_a["epoch_time_ms"] = df_a["time"].astype(int) / 1000
df_a = df_a.sort_values("time")
fig_a = px.line(df_a, x="time", y="bacteria_count", line_shape="hv", markers=True, color='bacteria_type')
fig_a.update_traces(mode="markers+lines", hovertemplate=None)
fig_a.update_layout(hovermode='x unified')


df_b = pd.DataFrame({"time":pd.Series(pd.date_range("1-nov-2021","2-nov-2021", freq="S")).sample(30),
             "bacteria_count":np.random.randint(0,500, 30), "bacteria_type":np.random.choice(list("BC"),30)})
df_b["epoch_time_ms"] = df_b["time"].astype(int) / 1000
df_b = df_b.sort_values("time")
fig_b = px.line(df_b, x="epoch_time_ms", y="bacteria_count", line_shape="hv", markers=True, color='bacteria_type')
fig_b.update_traces(mode="markers+lines", hovertemplate=None)
fig_b.update_layout(hovermode='x unified')


app = dash.Dash(__name__)  # call flask server
app.layout = html.Div(children=[
                          html.Div([
                              html.Div([
                                  html.H1(children='G_A'),
                                  dcc.Graph(id='fig_a-graph', figure=fig_a)
                              ], className='six columns'),
                              html.Div([
                                  html.H1(children='G_B'),
                                  dcc.Graph(id='fig_b-graph', figure=fig_b)
                              ], className='six columns')
                          ])])


if __name__ == '__main__':
    app.run_server(debug=True, port=8086)

我想达到:

  1. 两个 figures/graphs 中的迹线一致且唯一,因此两个图中迹线 'B' 的颜色相同,迹线 'A' 的颜色不会用作跟踪的颜色 'C'(也不 'B')。
  2. 有时,我在每张图中有 20 条轨迹,如果 plotly 可以 select 所有轨迹的颜色更鲜明,那就太好了,因为有时,很难分辨哪个是哪个,当颜色多笔交易不同但非常相似。

谢谢!

如果我没理解错的话,我想你需要的是这个:https://plotly.com/python/discrete-color/

向下滚动(或搜索)“color_discrete_map”

基本上,您可以创建一个字典,指定“轨迹 A”应使用颜色 1,“轨迹 B”应使用颜色 2,等等

然后在所有相关的figures/graphs中指定使用与color_discrete_map

相同的字典

一种方法是连接数据并使用构面。因此传说是共享和一致的。我在这里使用的 技巧 是创建一个额外的串联列,可以用作 facet_row

px.line(
    pd.concat([df_a.assign(df="a"), df_b.assign(df="b")]),
    x="epoch_time_ms",
    y="bacteria_count",
    facet_row="df",
    line_shape="hv",
    markers=True,
    color="bacteria_type",
).update_traces(mode="markers+lines", hovertemplate=None).update_layout(
    hovermode="x unified"
)

方法 2

  • 在此示例中定义您自己的颜色映射cmap
  • 确保您查看所有 细菌类型 并使用和方法在 dict comprehension
  • 中分配颜色
import pandas as pd
import numpy as np
import plotly.express as px
from dash.dependencies import Output, Input
from dash import dcc
from dash import html
import dash
from jupyter_dash import JupyterDash


df_a = pd.DataFrame(
    {
        "time": pd.Series(pd.date_range("1-nov-2021", "2-nov-2021", freq="S")).sample(
            30
        ),
        "bacteria_count": np.random.randint(0, 500, 30),
        "bacteria_type": np.random.choice(list("AB"), 30),
    }
)

df_a["epoch_time_ms"] = df_a["time"].astype(int) / 1000
df_a = df_a.sort_values("time")
df_b = pd.DataFrame(
    {
        "time": pd.Series(pd.date_range("1-nov-2021", "2-nov-2021", freq="S")).sample(
            30
        ),
        "bacteria_count": np.random.randint(0, 500, 30),
        "bacteria_type": np.random.choice(list("BC"), 30),
    }
)
df_b["epoch_time_ms"] = df_b["time"].astype(int) / 1000
df_b = df_b.sort_values("time")

# use whatever approach you want to assign a color to a bacteria type
# key loop through all bacteria types
cmap = {
    bt: px.colors.qualitative.Plotly[i % len(px.colors.qualitative.Plotly)]
    for i, bt in enumerate(pd.concat([df_a, df_b])["bacteria_type"].unique())
}

fig_a = px.line(
    df_a,
    x="time",
    y="bacteria_count",
    line_shape="hv",
    markers=True,
    color="bacteria_type",
    color_discrete_map=cmap,
)
fig_a.update_traces(mode="markers+lines", hovertemplate=None)
fig_a.update_layout(hovermode="x unified")


fig_b = px.line(
    df_b,
    x="epoch_time_ms",
    y="bacteria_count",
    line_shape="hv",
    markers=True,
    color="bacteria_type",
    color_discrete_map=cmap,
)
fig_b.update_traces(mode="markers+lines", hovertemplate=None)
fig_b.update_layout(hovermode="x unified")

# app = dash.Dash(__name__)  # call flask server
app = JupyterDash(__name__)

app.layout = html.Div(
    children=[
        html.Div(
            [
                html.Div(
                    [
                        html.H1(children="G_A"),
                        dcc.Graph(id="fig_a-graph", figure=fig_a),
                    ],
                    className="six columns",
                ),
                html.Div(
                    [
                        html.H1(children="G_B"),
                        dcc.Graph(id="fig_b-graph", figure=fig_b),
                    ],
                    className="six columns",
                ),
            ]
        )
    ]
)


if __name__ == "__main__":
    # app.run_server(debug=True, port=8086)
    # app.run_server(debug=True, port=8086)
    app.run_server(mode="inline")