如何调整绘图条高度并仅显示条的边(在子图中)?

2024-10-04 03:22:52 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我第一次有计划地尝试。与matplotlib和bokeh相比,我喜欢它的易用性。然而,关于如何美化我的情节,我仍然停留在一些基本的问题上。首先,这是下面的代码(功能齐全,只需复制和粘贴!):

import plotly.express as px
from plotly.subplots import make_subplots
import plotly as py
import pandas as pd
from plotly import tools

d = {'Mkt_cd': ['Mkt1','Mkt2','Mkt3','Mkt4','Mkt5','Mkt1','Mkt2','Mkt3','Mkt4','Mkt5'],
       'Category': ['Apple','Orange','Grape','Mango','Orange','Mango','Apple','Grape','Apple','Orange'],
           'CategoryKey': ['Mkt1Apple','Mkt2Orange','Mkt3Grape','Mkt4Mango','Mkt5Orange','Mkt1Mango','Mkt2Apple','Mkt3Grape','Mkt4Apple','Mkt5Orange'],
            'Current': [15,9,20,10,20,8,10,21,18,14],
           'Goal': [50,35,21,44,20,24,14,29,28,19]
     }
dataset  = pd.DataFrame(d)

grouped = dataset.groupby('Category', as_index=False).sum()
data = grouped.to_dict(orient='list')
v_cat = grouped['Category'].tolist()
v_current = grouped['Current']
v_goal = grouped['Goal']
fig1 = px.bar(dataset, x = v_current, y = v_cat, orientation = 'h',
              color_discrete_sequence = ["#ff0000"],height=10)
fig2 = px.bar(dataset, x = v_goal, y = v_cat, orientation = 'h',height=15)

trace1 = fig1['data'][0]
trace2 = fig2['data'][0]
fig = make_subplots(rows = 1, cols = 1, shared_xaxes=True, shared_yaxes=True)
fig.add_trace(trace2, 1, 1)
fig.add_trace(trace1, 1, 1)
fig.update_layout(barmode = 'overlay')
fig.show()

以下是输出: enter image description here

问题1:如何使v_电流(以红色条显示)的宽度变小?和中一样,它的高度应该更小,因为这是一个水平杆。我为trace1添加了10的高度,为trace2添加了15的高度,但它们仍然以相同的高度显示

问题2:有没有办法让v_目标(以蓝色条显示)只显示其右边缘,而不是填充条?大概是这样的: enter image description here

如果您注意到了,我还在每个类别下添加了一行。有没有一个快速的方法来添加这个?不是交易破坏者,只是奖金。我正在尝试做的其他事情是添加动画,等等,但那是为了其他时间

提前感谢您的回答


Tags: importappledata高度asfigplotlydataset
2条回答

您可以使用Plotly Express然后直接访问所描述的@vesland的figure对象,但我个人更喜欢使用graph_objects在一个地方进行所有更改

我还将指出,由于您正在一个图表中堆叠条形图,因此不需要子图。您可以使用fig = go.Figure()创建一个graph_object并添加跟踪以获得堆叠的条带,类似于您已经做的

对于问题1,如果您使用go.Bar(),则可以传递一个宽度参数。但是,这是以位置轴为单位的,因为y轴是分类的,所以宽度=1将填充整个类别,所以我选择了红色条的宽度=0.25,蓝色条的宽度=0.3(稍大),因为这似乎是您的意图

对于问题2,我唯一想到的是一个黑客。将条拆分为两个部分(一个部分的高度=原始高度-1),并将其不透明度设置为0,使其透明。然后将高度为1的下杆放在透明杆的顶部

如果不希望记录道显示在图例中,可以通过将showlegend=False传递到fig.add_trace来为每个条单独设置,或者通过将showlegend=False传递到fig.update_layout方法来完全隐藏图例

import plotly.express as px
import plotly.graph_objects as go
# from plotly.subplots import make_subplots
import plotly as py
import pandas as pd
from plotly import tools

d = {'Mkt_cd': ['Mkt1','Mkt2','Mkt3','Mkt4','Mkt5','Mkt1','Mkt2','Mkt3','Mkt4','Mkt5'],
       'Category': ['Apple','Orange','Grape','Mango','Orange','Mango','Apple','Grape','Apple','Orange'],
           'CategoryKey': ['Mkt1Apple','Mkt2Orange','Mkt3Grape','Mkt4Mango','Mkt5Orange','Mkt1Mango','Mkt2Apple','Mkt3Grape','Mkt4Apple','Mkt5Orange'],
            'Current': [15,9,20,10,20,8,10,21,18,14],
           'Goal': [50,35,21,44,20,24,14,29,28,19]
     }
dataset  = pd.DataFrame(d)

grouped = dataset.groupby('Category', as_index=False).sum()
data = grouped.to_dict(orient='list')
v_cat = grouped['Category'].tolist()
v_current = grouped['Current']
v_goal = grouped['Goal']

fig = go.Figure()

## you have a categorical plot and the units for width are in position axis units
## therefore width = 1 will take up the entire allotted space
## a width value of less than 1 will be the fraction of the allotted space
fig.add_trace(go.Bar(
    x=v_current,
    y=v_cat,
    marker_color="#ff0000",
    orientation='h',
    width=0.25
    ))

## you can show the right edge of the bar by splitting it into two bars
## with the majority of the bar being transparent (opacity set to 0)
fig.add_trace(go.Bar(
    x=v_goal-1,
    y=v_cat,
    marker_color="#ffffff",
    opacity=0,
    orientation='h',
    width=0.30,
    ))

fig.add_trace(go.Bar(
    x=[1]*len(v_cat),
    y=v_cat,
    marker_color="#1f77b4",
    orientation='h',
    width=0.30,
    ))

fig.update_layout(barmode='relative')
fig.show()

enter image description here

运行plotly.express将返回一个plotly.graph_objs._figure.Figure对象。运行go.Figure()plotly.graph_objects与例如go.Bar()一起运行的plotly.graph_objects也是如此。因此,在使用plotly express构建地物后,可以通过直接对地物的参照添加线或迹线,如:

fig['data'][0].width = 0.4

这正是你需要设置的酒吧宽度。您可以轻松地将其与plotly express结合使用:

代码1

fig = px.bar(grouped, y='Category', x = ['Current'],
             orientation = 'h', barmode='overlay', opacity = 1,
             color_discrete_sequence = px.colors.qualitative.Plotly[1:])
fig['data'][0].width = 0.4

图1

enter image description here

为了获得指示目标级别的条形或形状,您可以使用DerekO描述的方法,也可以使用:

for i, g in enumerate(grouped.Goal):
    fig.add_shape(type="rect",
                    x0=g+1, y0=grouped.Category[i], x1=g, y1=grouped.Category[i],
                    line=dict(color='#636EFA', width = 28))

完整代码:

import plotly.express as px
from plotly.subplots import make_subplots
import plotly as py
import pandas as pd
from plotly import tools

d = {'Mkt_cd': ['Mkt1','Mkt2','Mkt3','Mkt4','Mkt5','Mkt1','Mkt2','Mkt3','Mkt4','Mkt5'],
       'Category': ['Apple','Orange','Grape','Mango','Orange','Mango','Apple','Grape','Apple','Orange'],
           'CategoryKey': ['Mkt1Apple','Mkt2Orange','Mkt3Grape','Mkt4Mango','Mkt5Orange','Mkt1Mango','Mkt2Apple','Mkt3Grape','Mkt4Apple','Mkt5Orange'],
            'Current': [15,9,20,10,20,8,10,21,18,14],
           'Goal': [50,35,21,44,20,24,14,29,28,19]
     }
dataset  = pd.DataFrame(d)

grouped = dataset.groupby('Category', as_index=False).sum()

fig = px.bar(grouped, y='Category', x = ['Current'],
             orientation = 'h', barmode='overlay', opacity = 1,
             color_discrete_sequence = px.colors.qualitative.Plotly[1:])

fig['data'][0].width = 0.4
fig['data'][0].marker.line.width = 0

for i, g in enumerate(grouped.Goal):
    fig.add_shape(type="rect",
                    x0=g+1, y0=grouped.Category[i], x1=g, y1=grouped.Category[i],
                    line=dict(color='#636EFA', width = 28))
f = fig.full_figure_for_development(warn=False)
fig.show()

相关问题 更多 >