python Plotly彩条图例未显示最大值或最小值

n8ghc7c1  于 2023-06-04  发布在  Python
关注(0)|答案(8)|浏览(257)

我有一个带有颜色条图例的Plotly图表。
我想从0到100,每10个刻度。
无论我如何尝试,图表总是从10开始,到90结束,删除了我的顶部和底部。
如何确保显示顶部和底部的刻度?
MWE:

import numpy as np
import plotly.graph_objects as go

x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)

z = 100*xx*yy

figure = go.Figure()
figure.add_trace(
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            zmin=0,
            zmax=100,
            colorbar_tickvals=np.arange(0, 101, 10),
            colorbar_tickmode='array',
        )
)
figure.update_layout(
    template="simple_white",
)

figure.show()

7uzetpgm

7uzetpgm1#

根据official website,你应该加上这个。

contours=dict(
            start=0,
            end=100,
            size=10,
        ),

它看起来是这样的:

更新后的代码是

import numpy as np
import plotly.graph_objects as go

x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)

z = 100*xx*yy

figure = go.Figure()
figure.add_trace(
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            zmin=0,
            zmax=100,
            colorbar_tickvals=np.arange(0, 101, 10),
            colorbar_tickmode='array',
            contours=dict(
            start=0,
            end=100,
            size=10,
        ),
        )
)
figure.update_layout(
    template="simple_white",
)

figure.show()

根据我的经验,删除colorbar_tickvals=np.arange(0, 101, 10),colorbar_tickmode='array',后,图中没有变化。

6jygbczu

6jygbczu2#

我有个解决办法

import numpy as np
import plotly.graph_objects as go

x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)

z = 100*xx*yy

figure = go.Figure()
figure.add_trace(
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            zmin=0,
            zmax=100,
            colorbar = {'tickmode':'linear', 'tick0':0,'dtick':5, 'nticks':10}
        )
)
figure.update_layout(
    template="simple_white",
)

figure.show()

这将显示给定代码的顶部和底部刻度,但请注意它只从5到95。不幸的是,我尝试修改给定的参数,这就是它对nticks参数的说法:

Specifies the maximum number of ticks for the
particular axis. The actual number of ticks will be
chosen automatically to be less than or equal to
`nticks`. Has an effect only if `tickmode` is set to "auto".

希望这有帮助!
编辑:这是结果图

编辑:所以在浏览了你对这个问题的大量评论后,我意识到你想要:

  • 能够处理离散值
  • 以能够显示指定数组的结束值

基于这些假设,以下是针对您的问题的完整解决方案:
1.对于离散值:

colorbar = {'ticks':'inside', 'tickvals': [10, 30, 58, 76, 120]},
contours_coloring='heatmap'

这将为您的图生成如下离散值:

ticks参数接受'inside'或'outside',您可以根据自己的需要使用它
1.对于在颜色条中显示完整值的边:

colorbar = {'ticks':'inside', 'tickvals': [0, 10, 22, 25, 30, 58, 76, 77, 89, 100]},
contours_coloring='heatmap'

它会产生这样的图:

我希望这最终能解决你的问题

avwztpqn

avwztpqn3#

如果需要离散的颜色,我找到了@EricLavault的方法的替代解决方案,即交换到heatmap样式着色。
这利用了以下事实:

  • go.Heatmap显示开始和结束刻度
  • 您可以构造自定义色阶
  • 您可以显示/隐藏颜色栏

我写了一个小函数,你可以用它来生成一个 * 离散的 * 色标,你可以用一个空的go.Heatmap来实现想要的结果。

import plotly 
import numpy as np

def discrete_colorscale(n, colorscale="viridis"):
    """Generate a discretised version of a colorscale, with n discrete colors."""
    # Plotly colorscales are lists of float-color pairs, where the floats are
    # numbers in [0, 1] and the colors are Plotly color strings.
    # First, generate the float values. We want n colors, so we need n + 1 values.
    values = np.linspace(0, 1, n + 1)
    # Next, pick n colors from the colorscale.
    colors = plotly.colors.sample_colorscale(
        colorscale, n, low=0, high=1, colortype="rgb"
    )
    # We want the color to be constant for all values between two edges, so set
    # the color of the upper edge to be the same as the color of the lower edge.
    # This trick is described at https://plotly.com/python/colorscales/#constructing-a-discrete-or-discontinuous-color-scale
    lower_edges = [(values[i], colors[i]) for i in range(n)]
    upper_edges = [(values[i + 1], colors[i]) for i in range(n)]
    # This comprehension interleaves the two lists; resulting list is:
    # [lower_edges[0], upper_edges[0], lower_edges[1], upper_edges[1], ...]
    return [x for pair in zip(lower_edges, upper_edges) for x in pair]

使用这个函数看起来像这样:

import plotly.graph_objects as go


x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)

z = 100*xx*yy

figure = go.Figure()
figure.add_traces(
    [
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            zmin=0,   # Set zmin and zmax to ensure that the coloring is consistent
            zmax=100, # between the Contour and Heatmap
            ncontours=20, # We want 10 discrete colors, which means 20 contour lines
            colorscale=discrete_colorscale(10), # Same colorscale as the Heatmap
            showscale=False # Hide the Contour colorbar, because it doesn't show end ticks
        ),
        go.Heatmap(
            z=[None], # Dummy data - we only want the Heatmap colorbar
            y=[None],
            x=[None],
            zmin=0,   # Set zmin and zmax to ensure that the coloring is consistent
            zmax=100, # between the Contour and Heatmap
            colorscale=discrete_colorscale(10), # Same colorscale as the Contour
            showscale=True, # Show the heatmap colorbar
        )
    ]
)
# Adding the (empty) Heatmap trace messes up the axis ranges, so we need to set them manually
figure.update_xaxes(range=[0, 1])
figure.update_yaxes(range=[0, 1])

figure.show()

请注意,ncontours是离散颜色部分数量的两倍。
结果:

iovurdzv

iovurdzv4#

几乎可以肯定有更好的方法来实现这一点,但我认为您可以尝试修改zminzmax参数。从docstring:

"zmax
        Sets the upper bound of the color domain. Value should
        have the same units as in `z` and if set, `zmin` must
        be set as well."

因此,代码可以这样替换:

figure.add_trace(
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            zmin=-1,
            zmax=101,
            colorbar_tickvals=np.arange(0, 101, 10),
            colorbar_tickmode='array',
        )
)
wsewodh2

wsewodh25#

看看这是不是你要找的:

import numpy as np
import plotly.graph_objects as go

x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)

z = 100 * xx * yy

figure = go.Figure(
    go.Contour(
        z=z.flatten(),
        x=xx.flatten(),
        y=yy.flatten(),
        zmin=0,
        zmax=100,
        contours=dict(
            start=0,
            end=100,
            size=10,
        ),
    )
)

figure.update_layout(template="simple_white")

figure.show()

下面是我得到的输出:

hgncfbus

hgncfbus6#

方案一:使用 contours 参数,正如@agcgn所指出的。

import numpy as np
import plotly.graph_objects as go

x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)
z = 100*xx*yy

figure = go.Figure()
figure.add_trace(
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            # zmin=-100, # zmin zmax not necessary 
            # zmax=110,
            colorbar_tickvals=np.arange(0, 101, 10), # necessary, without it the legend text won't show 100
            # colorbar_tickmode='array', # colorbar_tickmode not necessary
            colorbar_len=1.2, # stretch the legend so it's vertically aligned with the contour lines in the plot
            contours=dict(
                start=0,
                end=100,
                size=10,
            ),
        )
)
figure.update_layout(
    template="simple_white",
    width=400,
    height=400
)

figure.show()

方案二:改变矩阵z的最小值和最大值,使min(z)< 0且max(z)> 100。

问题不在于传说,而在于等高线的真正含义。
您所要求的不是等高线图在plotly或其他绘图库中逻辑上可以提供的内容,给定矩阵z的当前值范围(0,100)。
A contour line ... is a curve along which the function has a constant value, so that the curve joins points of equal value.
在大小为50 × 50的矩阵z中,只有一个点z[49,49]的值为100。虽然有许多点的值为0,但它们只存在于矩阵的最顶部和最左边界。因此,从技术上讲,在矩阵“内部”不需要绘制曲线来连接值为0或100的点。

在图例上显示0和100而不直接指定等高线的唯一方法是修改矩阵z的最小最大值,使得min(z)< 0且max(z)> 100。只有这样,您才可以在轮廓中的0点之间绘制曲线<0 and of >,并在>100和<100的点之间绘制另一条曲线。

import numpy as np
import plotly.graph_objects as go

x = np.linspace(0, 1, 50)
y = np.linspace(0, 1, 50)
xx, yy = np.meshgrid(x, y)
z = 100*xx*yy

z[49,49] = 100.1; z[0,0] = -0.1

figure = go.Figure()
figure.add_trace(
        go.Contour(
            z=z.flatten(),
            x=xx.flatten(),
            y=yy.flatten(),
            # zmin=-100, # no need to specify zmin and zmax
            # zmax=110,
            colorbar_tickvals=np.arange(0, 101, 10),
            colorbar_tickmode='array',
            colorbar_len=1.2 # to stretch the legend so it keeps vertically aligned with the contours in the plot
        )
)
figure.update_layout(
    template="simple_white",
    width=400,
    height=400
)

figure.show()

oiopk7p5

oiopk7p57#

看看(plotly.js)负责绘制colorbar的代码,我认为这是一个bug,cf。我刚刚打开的issue
直到它被解决,你能做的最好的事情是使用“热图”轮廓着色方法(不受错误的影响),而不是默认的“填充”。等高线水平(边界)将保持不变,唯一的区别是:
如果“填充”,则在每个等高线级别之间均匀地进行着色。如果是“热图”,则在每个等高线级别之间应用热图梯度着色。

figure.add_trace(
    go.Contour(
        z=z.flatten(),
        x=xx.flatten(),
        y=yy.flatten(),
        zmin=0,
        zmax=100,
        colorbar_tickvals=np.arange(0, 101, 10),
        colorbar_tickmode='array',
        contours_coloring='heatmap'
    )
)

其他答案的问题在于,它们只是给予了硬编码的轮廓水平,而OP可能考虑绘制 * 任何 * 数据集的轮廓,而不仅仅是这个MWE,因此隐式使用autocontour(默认)。
此外,在示例中,第一个级别是10,结束是90。等值线高程表示其中包含数据的区域之间的边界。通过将contour start设置为0,不仅会影响色标,而且会在点(x=0,y=0,z=0)和小于10的相邻值之间添加一个轮廓,而它们应该在同一区域中具有相同的颜色(设置zmin=-1zmax=101会导致相同的问题:硬编码,坏结果)。
例如,在@agcgn的屏幕截图中,左下角出现的区域不应该存在。是的,它很小,但是看看x = y = np.linspace(0, 1, 5)会发生什么:

该区域被着色为“小于0”,而z不包括任何负值,输出就像不可预测的一样不一致。

o3imoua4

o3imoua48#

trace = go.Heatmap( colorscale=COLORSCALE,
                    colorbar = dict(
                        tickvals = [0,10,20,30,40,50,60,70,80,90,100],
                        tickmode = 'array',
                    )
                    ...
        )

在Python中是一种方式;在JS中几乎相同
但正如@Levent指出的那样,没有代码,我们无法告诉你你需要什么。

相关问题