Plotly: сортировка столбцов оси Y гистограммы с накоплением по значению

У меня есть этот пример кода, использующий plotly, который строит столбчатую диаграмму с накоплением:

import plotly.graph_objects as go

x = ['2018-01', '2018-02', '2018-03']

fig = go.Figure(go.Bar(x=x, y=[10, 15, 3], name='Client 1'))
fig.add_trace(go.Bar(x=x, y=[12, 7, 14], name='Client 2'))

fig.update_layout(
    barmode='stack',
    yaxis={'title': 'amount'},
    xaxis={
        'type': 'category',
        'title': 'month',
    },
)
fig.show()

На выходе получается следующий график:

введите описание изображения здесь

Есть ли способ настроить расположение графика, чтобы упорядочить ось Y каждого столбца по значению?
Например, на втором столбце (2018-02) Клиент 1 имеет более высокое значение для Y, синяя полоса должна быть включена верх красной.


person Teodor Ivanov    schedule 16.09.2020    source источник
comment
Это не делает его гистограммой с накоплением, не так ли? Первый уровень - это клиент 1, а второй уровень - это клиент 2. В barmode=group они упорядочиваются клиентом.   -  person r-beginners    schedule 16.09.2020
comment
Это правильно, но мне нужна эта диаграмма для представления большого количества данных. В некоторых случаях столбец может содержать более 15 столбцов, расположенных друг над другом. Мне это нужно, например, как альтернатива ленточному графику в Power BI.   -  person Teodor Ivanov    schedule 16.09.2020


Ответы (1)


В Plotly трассы всегда отображаются в том порядке, в котором они добавлены к фигуре, и нет опции компоновки, позволяющей изменить это поведение; см., например, этот ответ. Это означает, что для каждой даты вам нужно будет добавить трассы с меньшими значениями, прежде чем добавлять трассы с большими значениями. Я привел пример ниже, основанный на вашем коде.

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

# data
df = pd.DataFrame({'Date': ['2018-01', '2018-02', '2018-03'],
                   'Client 1': [10, 15, 3],
                   'Client 2': [12, 7, 14],
                   'Client 3': [18, 2, 7]})

# colors
colors = {'Client 1': 'red',
          'Client 2': 'blue',
          'Client 3': 'green'}

# traces
data = []

# loop across the different rows
for i in range(df.shape[0]):

    # for each row, order the columns based on
    # their values from smallest to largest
    ordered_columns = df.columns[1:][np.argsort(df.iloc[i, 1:].values)]

    # add a separate trace for each column,
    # ordered from smallest to largest
    for column in ordered_columns:

        data.append(go.Bar(x=[df['Date'][i]],
                           y=[df[column][i]],
                           marker=dict(color=colors[column]),
                           name=column,
                           legendgroup=column,
                           showlegend=i == 0)) # show the legend only once for each column

# layout
layout = dict(barmode='stack',
              yaxis={'title': 'amount'},
              xaxis={'type': 'category', 'title': 'month'})

# figure
fig = go.Figure(data=data, layout=layout)

fig.show()

введите описание изображения здесь

person Flavia Giammarino    schedule 16.09.2020
comment
Спасибо за решение! Я пробовал что-то подобное, но не знал, как обрабатывать повторяющиеся метки в легенде и цвета полос. - person Teodor Ivanov; 17.09.2020