用Python画马赛克|带有自定义颜色和标签的 marimekko 图表

问题描述 投票:0回答:1

我想用Python画马赛克 |带有自定义颜色和标签的 marimekko 图表。

以下代码可以正常工作

import plotly.graph_objects as go

year = ['2019', '2020', '2021', '2022']

fig1 = go. Figure() 

fig1.add_trace(go.Bar(x=year, y=[20, 18, 14, 10], text=['20', '18', '14', '10'], name='brand 1'))
fig1.add_trace(go.Bar(x=year, y=[10, 15, 20, 22], text=['10', '15', '20', '22'], name='brand 2'))
fig1.add_trace(go.Bar(x=year, y=[6,   8, 10, 12], text=[ '6',  '8', '10', '12'], name='brand 3'))

fig1.update_layout(barmode='stack')

fig1.write_image('test_1.png')    

但是,我想根据通过 y 传递的数据对每年的数据进行排序。这意味着代码看起来像(我将省略排序,这不是这里的问题)。

fig2.add_trace(go.Bar(x=year, y=[20, 18, 20, 22], text=['20: brand 1', '18: brand 1', '20: brand 2', '22: brand 2']))
fig2.add_trace(go.Bar(x=year, y=[10, 15, 14, 12], text=['10: brand 2', '15: brand 2', '14: brand 1', '12: brand 3']))
fig2.add_trace(go.Bar(x=year, y=[ 6,  8, 10, 10], text=[ '6: brand 3',  '8: brand 3', '10: brand 3', '10: brand 1']))

当然,我仍然希望每个品牌(而不是每个位置)使用相同的颜色,所以除了适当排序的数据外,我还需要为自定义标签文本(工作正常)和相应的自定义颜色传递两个数组(我不知道该怎么做)。

问题 1:如何将一组自定义颜色传递给每条迹线,以便每个品牌始终获得相同的颜色?有没有像

这样的
fig1.add_trace(go.Bar(x=year, y=[20, 18, 14, 10], colors=...))

问题2:是否有另一种创建马赛克的选项|不基于 plotly 的具有不同 x 宽度的 marimekko 图表?

预期的代码是这样的

# the color map 
the_brand_cmap = plt.get_cmap('seismic_r') 
the_brand_norm = co.TwoSlopeNorm(vmin=-max_abs, vcenter=0, vmax=max_abs)

...

for i in years: # the loop is over the years, not over the brabnds

    # some more code to sort df per year and to extract the brand names and colors

    fig1.add_trace(go.Bar(
        x=np.cumsum(xwidths) - xwidths,
        y=ysizes_norm, 
        width=xwidths,
        marker_color=the_brand_cmap(the_brand_norm(colors)), # the colors for each year
        text=brand_name)

预期的结果是

python colors plotly marimekko-chart
1个回答
0
投票

我根据 reference 中的示例使用您的数据创建了一个 Marimekko 图。为年份的组成添加一个新列。同样,创建一个包含年份总数的列宽。为了指定每个品牌的颜色,创建品牌和颜色的字典,并在创建带有品牌提取数据的堆叠图时指定。

import plotly.graph_objects as go
import numpy as np
import pandas as pd

year = ['2019', '2020', '2021', '2022']
data = {'brand 1': [20, 18, 14, 10],
       'brand 2': [10, 15, 20, 22],
       'brand 3': [6,   8, 10, 12]
       }

df = pd.DataFrame.from_dict(data)

df = df.T
df.columns = year
for c in df.columns:
    df[c+'_%'] = df[c].apply(lambda x: (x / df.loc[:,c].sum()) * 100)

widths = np.array([sum(df['2019']), sum(df['2020']), sum(df['2021']), sum(df['2022'])])
marker_colors = {'brand 1': 'darkblue', 'brand 2': 'darkgreen', 'brand 3': 'crimson'}

fig1 = go.Figure()

for idx in df.index:
    dff = df.filter(items=[idx], axis=0)
    fig1.add_trace(go.Bar(
        x=np.cumsum(widths) - widths,
        y=dff[dff.columns[4:]].values[0],
        width=widths,
        marker_color=marker_colors[idx],
        text=['{:.2f}%'.format(x) for x in dff[dff.columns[4:]].values[0]],
        name=idx
    )
)

fig1.update_xaxes(
    tickvals=np.cumsum(widths)-widths,
    ticktext= ["%s<br>%d" % (l, w) for l, w in zip(year, widths)]
)

fig1.update_xaxes(range=[0, widths])
fig1.update_yaxes(range=[0, 100])

fig1.update_layout(barmode='stack')

#fig1.write_image('test_1.png')
fig1.show()

© www.soinside.com 2019 - 2024. All rights reserved.