Plotly中的条件格式

时间:2018-08-08 14:16:40

标签: python plotly plotly-dash plotly.js

这个问题是关于如何在Plotly中进行条件格式化的。

可能需要这样做的实例:

  • 散点图,其中需要根据2变量对点进行着色(即彩虹);
  • 交互式图表,其中颜色取决于参数值;
  • 直方图,其中部分颜色需要不同。

在这里,我将专门询问直方图。

获取以下数据:

data = np.random.normal(size=1000)

我想要一个直方图,其中将高于0的值归为另一种颜色。

一个简单的解决方案是

hist1 = go.Histogram(x=data[data<0], 
                    opacity=0.75, 
                    histnorm='density',
                    showlegend=False,
                    )
hist2 = go.Histogram(x=data[data>=0], 
                    opacity=0.75, 
                    histnorm='density',
                    showlegend=False,
                    )
layout = go.Layout(barmode='overlay')
fig = go.Figure(data=[hist1, hist2], layout=layout)
iplot(fig, show_link=False)

enter image description here

此解决方案存在几个问题:

  1. 这2组默认箱大小不同,导致零重叠。
  2. 如果我想让histnorm = 'probability density'的结果图对每个单独的直方图进行“归一化”,那么它们看起来将不成比例。
  3. 两个直方图的分箱都是从左开始的,因此最后一个分箱可能会超出零以下值的直方图。

有更好的方法吗?


更新

好的,我可以使用xbins解决(1)和(3):

hist1 = go.Histogram(x=data[data>=0], 
                    opacity=0.75, 
                    xbins=dict(
                        start=0,
                        end=4,
                        size=0.12),
                    histnorm='density',
                    showlegend=False,
                    )
hist2 = go.Histogram(x=data[data<0], 
                    opacity=0.75, 
                    xbins=dict(
                        start=-0.12*33,
                        end=0,
                        size=0.12),
                    histnorm='density',
                    showlegend=False,
                    )
layout = go.Layout(barmode='overlay')
fig = go.Figure(data=[hist1, hist2], layout=layout)
iplot(fig, show_link=False)

enter image description here

但是,我该如何解决第二个问题?

1 个答案:

答案 0 :(得分:1)

对于...

  

如果我想让histnorm ='概率密度',那么得出的图   “归一化”每个单独的直方图,因此它们看起来   不相称的。

...部分看来,您必须将整个样本归一化,然后再将其分成两个不同的直方图。这意味着您应该要做的是制作一个area chart with multiple colors under a single trace。但是,不幸的是,建议的解决方案似乎是使用...将不同的颜色分配给两条迹线。

df_pos = df.where(df < 0, 0)
df_neg = df.where(df > 0, 0)

...当然可以带您回到原来的位置。

因此,要获得所需的内容,似乎您必须摆脱gi.Histogram的局限,首先要对装仓和归一化进行分类,然后再使用面积图或条形图的组合图表。据我了解,这将解决所有三个要点。这是有关此操作的建议:

情节:

enter image description here

代码:

# imports
import plotly.graph_objects as go
from plotly.offline import iplot
import pandas as pd
import numpy as np

# theme
import plotly.io as pio
#pio.templates
#pio.templates.default = "plotly_white"
pio.templates.default = "none"

# Some sample data
np.random.seed(123)
x = np.random.normal(0, 1, 1000)

# numpy binning
binned = np.histogram(x, bins=30, density=True)

# retain some info abou the binning
yvals=binned[0]
x_last = binned[1][-1]
xvals=binned[1][:-1]

# organize binned data in a pandas dataframe
df_bin=pd.DataFrame(dict(x=xvals, y=yvals))
df_bin_neg = df.where(df['x'] < 0)
df_bin_pos = df.where(df['x'] > 0)

# set up plotly figure
fig=go.Figure()

# neagtive x
fig.add_trace(go.Scatter(
    x=df_bin_neg['x'],
    y=df_bin_neg['y'],
    name="negative X",
    hoverinfo='all',
    fill='tozerox',
    #fillcolor='#ff7f0e',
    fillcolor='rgba(255, 103, 0, 0.7)',

    line=dict(color = 'rgba(0, 0, 0, 0)', shape='hvh')
))

# positive x
fig.add_trace(go.Scatter(
    x=df_bin_pos['x'],
    y=df_bin_pos['y'],
    name="positive X",
    hoverinfo='all',
    fill='tozerox',
    #opacity=0.2,
    #fillcolor='#ff7f0e',
    #fillcolor='#1f77b4',
    fillcolor='rgba(131, 149, 193, 0.9)',
    line=dict(color = 'rgba(0, 0, 0, 0)', shape='hvh')
))

# adjust layout to insure max values are included
ymax = np.max([df_bin_neg['y'].max(), df_bin_neg['y'].max()])
fig.update_layout(yaxis=dict(range=[0,ymax+0.1]))

# adjust layout to match OPs original
fig.update_xaxes(showline=True, linewidth=1, linecolor='black', mirror=False, zeroline=False, showgrid=False)
fig.update_yaxes(showline=False)#, linewidth=2, linecolor='black', mirror=True)

fig.show()