与多个类别的块框图

发布于 2025-02-11 08:48:01 字数 2821 浏览 0 评论 0原文

考虑以下玩具数据:

import pandas as pd
import numpy as np
from plotly import graph_objects as go
from plotly.subplots import make_subplots

np.random.seed(42)

df = pd.DataFrame(
    {
        "val1": np.random.normal(0, 1, size=100),
        "val2": np.random.normal(5, 2, size=100),
        "cat": np.random.choice(["a", "b"], size=100),
    }
)

哪些产量(前5行):

Val1Val2CAT
00.4967142.16926B
1-0.1382644.15871B
20.6476894.31457A
31.523033.39545B
4-0.2341534.67743

我的目标是让每个目标都包含两个盒子,一个盒子(一个盒子)(一个盒子)(一个盒子)(一个盒子)(一个盒子)(一个盒子)(一个盒子)

以下代码:

fig = make_subplots(rows=2, cols=1, subplot_titles=["Value 1 dist", "Value 2 dist"])

fill_colors = {"a": "rgba(150, 25, 40, 0.5)", "b": "rgba(25, 150, 40, 0.5)"}

for i, val in enumerate(["val1", "val2"]):
    for c in df["cat"].unique():
        dff = df[df["cat"] == c]
        fig.add_trace(
            go.Box(
                y=dff[val],
                x=dff["cat"],
                boxmean="sd",
                name=c,
                showlegend=True if val=="val1" else False,
                fillcolor=fill_colors[c],
                line={"color": fill_colors[c]},
            ),
            row=i + 1,
            col=1,
        )

使我非常接近:

  1. ​情节周期?因此,结果与其他图兼容。请注意,我对颜色进行了硬编码...
  2. 左侧的传奇;是否有一种只有单个传说的程序化方法?请注意,如果val ==“ val1” else false ,我使用showlegend = true。
  3. 奖励:我如何控制盒子的顺序(即

我在过去两个相关问题中发布的盒子的顺序( 例如,哪个类别是第一个?) /a> and 在这里),但是那里的答案并没有帮助我按照我的意愿调整我的情节。

Consider the following toy data:

import pandas as pd
import numpy as np
from plotly import graph_objects as go
from plotly.subplots import make_subplots

np.random.seed(42)

df = pd.DataFrame(
    {
        "val1": np.random.normal(0, 1, size=100),
        "val2": np.random.normal(5, 2, size=100),
        "cat": np.random.choice(["a", "b"], size=100),
    }
)

which yields (top 5 rows):

val1val2cat
00.4967142.16926b
1-0.1382644.15871b
20.6476894.31457a
31.523033.39545b
4-0.2341534.67743a

My objective is to get two box plots each containing two boxes (one per category).

Following code:

fig = make_subplots(rows=2, cols=1, subplot_titles=["Value 1 dist", "Value 2 dist"])

fill_colors = {"a": "rgba(150, 25, 40, 0.5)", "b": "rgba(25, 150, 40, 0.5)"}

for i, val in enumerate(["val1", "val2"]):
    for c in df["cat"].unique():
        dff = df[df["cat"] == c]
        fig.add_trace(
            go.Box(
                y=dff[val],
                x=dff["cat"],
                boxmean="sd",
                name=c,
                showlegend=True if val=="val1" else False,
                fillcolor=fill_colors[c],
                line={"color": fill_colors[c]},
            ),
            row=i + 1,
            col=1,
        )

Brings me very close:

Initial result

Here are the things I would like to adjust:

  1. How do I get, programmatically, the first 2 (or n) colors used in the default cycle of Plotly? So the result is compatible with other plots. Note that I hardcoded the colors...
  2. The legend on the left; is there a more programmatic way to have only single legend? Note that I used showlegend=True if val=="val1" else False.
  3. Bonus: How can I control the order of the boxes (i.e. which category comes first?)

I posted in the past two related questions (here and here) but the answers there didn't help me tune me plot as I want.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

计㈡愣 2025-02-18 08:48:01
  1. 请参阅官方参考如何获得颜色
    标准颜色集的名称。您可以在一个中获得颜色名称
    列表。

  2. 关于控制重复的传奇,我个人没有
    我使用方法的问题,这是一种常见的方法,
    但是,如果我要编程处理,我会使用set()
    通过添加重复的传奇名称来使其与众不同。我学到了这个
    提示来自 a>。


  3. 第三个是按类别订购,您可以指定上升或
    按类别下降订单。

这是没有得到预期答案的人的回应。我以前的答案不令人满意?我会尽可能回复。

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

# https://plotly.com/python/discrete-color/#color-sequences-in-plotly-express
plotly_default = px.colors.qualitative.Plotly
print(plotly_default)

fig = make_subplots(rows=2, cols=1, subplot_titles=["Value 1 dist", "Value 2 dist"])

fill_colors = {"a": plotly_default[0], "b": plotly_default[1]}

for i, val in enumerate(["val1", "val2"]):
    for c in df["cat"].unique():
        dff = df[df["cat"] == c]
        fig.add_trace(
            go.Box(
                y=dff[val],
                x=dff["cat"],
                boxmean="sd",
                name=c,
                showlegend=True, # if val=="val1" else False,
                fillcolor=fill_colors[c],
                line={"color": fill_colors[c]},
                opacity=0.5
            ),
            row=i + 1,
            col=1,
        )
names = set()
fig.for_each_trace(
    lambda trace:
        trace.update(showlegend=False)
        if (trace.name in names) else names.add(trace.name))

fig.update_xaxes(categoryorder='category ascending')
fig.update_layout(legend=dict(traceorder='reversed'))
fig.show()

  1. Please refer to the official reference for how to get the color
    names for a standard color set. You can get the color names in a
    list.

  2. As for controlling duplicate legends, I personally don't have a
    problem with your method as I use it and it is a common approach,
    but if I were to handle it programmatically, I would use set() to
    make it unique by adding the duplicate legend names. I learned this
    Tips from this answer.

  3. The third is to order by category, you can specify ascending or
    descending order by category.

This is a response from someone who did not get the expected answer. What was unsatisfactory about my previous answers? I will respond whenever possible.

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

# https://plotly.com/python/discrete-color/#color-sequences-in-plotly-express
plotly_default = px.colors.qualitative.Plotly
print(plotly_default)

fig = make_subplots(rows=2, cols=1, subplot_titles=["Value 1 dist", "Value 2 dist"])

fill_colors = {"a": plotly_default[0], "b": plotly_default[1]}

for i, val in enumerate(["val1", "val2"]):
    for c in df["cat"].unique():
        dff = df[df["cat"] == c]
        fig.add_trace(
            go.Box(
                y=dff[val],
                x=dff["cat"],
                boxmean="sd",
                name=c,
                showlegend=True, # if val=="val1" else False,
                fillcolor=fill_colors[c],
                line={"color": fill_colors[c]},
                opacity=0.5
            ),
            row=i + 1,
            col=1,
        )
names = set()
fig.for_each_trace(
    lambda trace:
        trace.update(showlegend=False)
        if (trace.name in names) else names.add(trace.name))

fig.update_xaxes(categoryorder='category ascending')
fig.update_layout(legend=dict(traceorder='reversed'))
fig.show()

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文