简体   繁体   English

Plotly:排序多类别条形图

[英]Plotly: Sort multicategory bar chart

I have some problems sorting a multicategorial chart.我在对多类别图表进行排序时遇到了一些问题。

Some example code.一些示例代码。

import pandas as pd
import plotly.graph_objects as go

data = [
    [0, "Born", 4, "Rhino"],  # commenting this line will also reverse sub category sorting
    [0, "Died", -1, "Rhino"],
    [1, "Born", 4, "Lion"],
    [1, "Died", -1, "Lion"],
    [2, "Born", 12, "Rhino"],
    [2, "Died", -5, "Lion"],
]
z_data = list(zip(*data))

df = pd.DataFrame({
    "tick": z_data[0],
    "category": z_data[1],
    "value": z_data[2],
    "type": z_data[3],
})
df = df.sort_values(by=['tick', 'category', 'value', 'type'])
print(df)
fig = go.Figure()
for t in df.type.unique():
    plot_df = df[df.type == t]
    fig.add_trace(go.Bar(
        x=[plot_df.tick, plot_df.category],
        y=abs(plot_df.value),
        name=t,
    ))
fig.update_layout({
    'barmode': 'stack',
    'xaxis': {
        'title_text': "Tick",
        'tickangle': -90,
    },
    'yaxis': {
        'title_text': "Value",
    },
})
fig.write_html(str("./diagram.html"))

未注释 评论

As you can see the tick 2 is before tick 1. This happens because the 'Rhino' is the first in type list, which will create the tick 0 and 2. The lion bars are added after with tick 1. But how can i sort the bars properly now?如您所见,刻度 2 在刻度 1 之前。发生这种情况是因为“犀牛”是类型列表中的第一个,它将创建刻度 0 和 2。狮子条是在刻度 1 之后添加的。但是我该如何排序酒吧现在好吗?

PS.附注。 'barmode': 'stack' is on purpose. 'barmode': 'stack'是故意的。 Even if it is not used in this test example.即使在这个测试示例中没有使用它。

I'm able to fix the tick but not the born/died order.我能够修复滴答声,但不能修复出生/死亡顺序。 I'm planning to plot row by row so I need to play with showlegend我打算逐行绘制,所以我需要玩 showlegend

Data数据

import pandas as pd
import plotly.graph_objects as go
data = [
    [0, "Born", 4, "Rhino"],  # commenting this line will also reverse sub category sorting
    [0, "Died", -1, "Rhino"],
    [1, "Born", 4, "Lion"],
    [1, "Died", -1, "Lion"],
    [2, "Born", 12, "Rhino"],
    [2, "Died", -5, "Lion"],
]
# you don't really need to zip here
df = pd.DataFrame(data, columns=["tick", "category", "value", "type"])
df["value"] = df["value"].abs()

Set color设置颜色

In case you have more types there are answer here that can help you.如果您有更多类型,这里有答案可以帮助您。 Check doc检查文档

color_diz = {"Rhino": "blue", "Lion": "red"}
df["color"] = df["type"].map(color_diz)

Show Legend显示图例

Here I want to show the legend for the first occurrence of every type在这里,我想显示每种类型第一次出现的图例

grp = df.groupby("type")\
        .apply(lambda x: x.index.min())\
        .reset_index(name="idx")

df = pd.merge(df, grp, on=["type"], how="left")

df["showlegend"] = df.index == df["idx"]

Data to plot要绘制的数据

print(df)
   tick category  value   type color  idx  showlegend
0     0     Born      4  Rhino  blue    0        True
1     0     Died      1  Rhino  blue    0       False
2     1     Born      4   Lion   red    2        True
3     1     Died      1   Lion   red    2       False
4     2     Born     12  Rhino  blue    0       False
5     2     Died      5   Lion   red    2       False

Plot阴谋

fig = go.Figure()
for i, row in df.iterrows():
    fig.add_trace(
        go.Bar(x=[[row["tick"]], [row["category"]]],
               y=[row["value"]],
               name=row["type"],
               marker_color=row["color"],
               showlegend=row["showlegend"],
               legendgroup=row["type"] # Fix legend
               ))
    
fig.update_layout({
    'barmode': 'stack',
    'xaxis': {
        'title_text': "Tick",
        'tickangle': -90,
    },
    'yaxis': {
        'title_text': "Value",
    },
})
fig.show()

在此处输入图片说明

EDIT编辑

If you have more type you could use the following trick.如果您有更多type您可以使用以下技巧。

First I generate different types首先我生成不同的类型

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

df = pd.DataFrame({"type":np.random.choice(list(string.ascii_lowercase), 100)})

Then I pick a color sequence from doc and put them on a dictionary然后我从文档中选择一个颜色序列并将它们放在字典中

color_dict = {k:v for k,v in enumerate(px.colors.qualitative.Plotly)}

Then I put the unique type on a dataframe然后我将唯一type放在数据框上

df_col = pd.DataFrame({"type": df["type"].unique()})

and I assign each of them a color according to its index我根据它的索引为每个人分配一种颜色

df_col["color"] = (df_col.index%len(color_dict)).map(color_dict)

Finally I merge to the original df最后我合并到原来的 df

df = pd.merge(df, df_col, on=["type"], how="left")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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