pandas 绘制:条形图,颜色为红色〈0,绿色>0,按组划分

snz8szmq  于 2023-01-28  发布在  其他
关注(0)|答案(3)|浏览(197)

给定具有2个组的 Dataframe :(组1,组2),其具有大于和小于0的值:情节:

  • 条形图
  • x = x
  • y =数值,除以组1、组2
  • 如果值〈0,颜色=红色,如果值〉0,颜色=绿色
  • 图例显示group1、group2为不同颜色。

然而,我当前的代码并没有像我所期望的那样着色,并且图例显示为相同的颜色:

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

df = pd.DataFrame( {
    "x" : [1,2,3],
    "group1" : [np.nan, 1, -0.5],
    "group2" : [np.nan, -0.2, 1],  
}).set_index("x")

df_ = df.reset_index().melt(id_vars = 'x')
fig = px.bar(df_, x='x', y='value', color='variable', barmode='group')
fig.update_traces(marker_color=['red' if val < 0 else 'green' for val in df_['value']], marker_line_color='black', marker_line_width=1.5)
fig.show()

OUT,并指出我想要实现的目标:

am46iovg

am46iovg1#

由于express无法实现这一点,因此我们使用graph对象为每个组绘制条形图,对于第1组和第2组,更改了通过数值确定颜色的逻辑,更改了第1组和第2组的条件,原因是如果不这样做,图例将不会进行颜色编码。

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

df = pd.DataFrame( {
    "x" : [1,2,3],
    "group1" : [np.nan, 1, -0.5],
    "group2" : [np.nan, -0.2, 1],  
}).set_index("x")

df_ = df.reset_index().melt(id_vars = 'x')

fig = go.Figure()

fig.add_trace(go.Bar(x=df_.query('variable =="group1"')['x'],
                     y=df_.query('variable =="group1"')['value'],
                     marker_color=['red' if val < 0 else 'green' for val in df_.query('variable =="group1"')['value']],
                     marker_line_color='black',
                     marker_line_width=1.5,
                     name='group1',
                     #legendgroup='group1'
                    )
             )

fig.add_trace(go.Bar(x=df_.query('variable =="group2"')['x'],
                     y=df_.query('variable =="group2"')['value'],
                     marker_color=['green' if val > 0 else 'red' for val in df_.query('variable =="group2"')['value']],
                     marker_line_color='black',
                     marker_line_width=1.5,
                     name='group2',
                     #legendgroup='group2'
                    )
             )
fig.update_layout(barmode='group', xaxis=dict(title_text='x'), yaxis=dict(title_text='value'))
fig.show()

7qhs6swi

7qhs6swi2#

如果您想根据x值(而不是variable组)对条形图上色,则必须单独更新轨迹(或手动绘制图形对象):

fig = px.bar(df_, x='x', y='value', color='variable', barmode='group')
fig.for_each_trace(
    lambda trace: trace.update(marker_color=np.where(df_.loc[df_['variable'].eq(trace.name), 'value'] < 0, 'red', 'green'))
)
fig.update_layout(showlegend=False)  # Hide legend because there is no distinct group
fig.show()

输出:

4urapxun

4urapxun3#

为了坚持使用plotly.express,我会在 Dataframe 中添加一列,例如,df_['positive']带有布尔值,然后用这个变量给图着色。
它看起来像这样:

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

df = pd.DataFrame( {
    "x" : [1,2,3],
    "group1" : [np.nan, 1, -0.5],
    "group2" : [np.nan, -0.2, 1],  
}).set_index("x")

df_ = df.reset_index().melt(id_vars = 'x')
df_['positive'] = (df_['value']>=0)

fig = px.bar(df_, x='x', y='value',barmode = 'group',
                color='positive',
                color_discrete_map={
                    True: 'green',
                    False: 'red'
                    }
)
fig.update_traces(marker_line_color='black', marker_line_width=1.5)
fig.show('browser')

其产生如下:

编辑以下评论

如果你想保持plotly.express内的颜色和组的区别,一种方法可以是添加模式...

溶液1:每个组合都有其图例条目
df = pd.DataFrame( {
    "x" : [1,2,3],
    "group1" : [np.nan, 1, -0.5],
    "group2" : [np.nan, -0.2, 1],  
}).set_index("x")

df_ = df.reset_index().melt(id_vars = 'x')
positive = (df_['value']>=0)
df_['positive'] = positive
df_['sign'] = ['positive' if x else 'negative' for x in df_['positive']]
# Each compbination of color and patterns
fig = px.bar(df_, x='x', y='value',barmode = 'group',
                color='sign',
                color_discrete_map={
                    'positive': 'green',
                    'negative': 'red'
                    },
                pattern_shape="variable")
fig.update_layout(legend_title="Groups & Signs", bargap=0.5,bargroupgap=0.1)
fig.show('browser')

其输出以下

溶液2:图例仅反映模式
# Only patterns in legend
fig = px.bar(df_, x='x', y='value', color='variable',
                barmode='group',pattern_shape="variable")
fig.update_layout(legend_title="Groups", bargap=0.5,bargroupgap=0.1)
fig.for_each_trace(
    lambda trace: trace.update(marker_color=np.where(df_.loc[df_['variable'].eq(trace.name), 'value'] < 0, 'red', 'green'))
)
fig.show('browser')

其输出:

然而,我无法从图例中"删除"绿色...

相关问题