为了账号安全,请及时绑定邮箱和手机立即绑定

Plotly:如何创建具有多颜色标签的时间序列变量的线图?

Plotly:如何创建具有多颜色标签的时间序列变量的线图?

繁花如伊 2023-09-26 14:17:35
我有一个作为 df 的数据帧,它有一列我在 y 下作为“参数”传递,如下所示,并将其根据变量“时间”绘制。该变量在“标签”列下有 2 个标签,该标签在颜色下传递。import plotly.express as px fig= px.line(data_frame= df,  x='time', y='parameter', color='labels')请找到我为图表附加的图像。两张图片都具有相同的变量,但第二张图片是第一张图片的缩放版本,以便更好地了解。正如你所看到的,我正在绘制一个变量与时间的关系,并期望两个标签有不同的颜色,plotly在图表中给出了两条单独的线,颜色为蓝色和红色,看起来非常混乱和错误。我应该进行哪些更改才能获得 2 种不同颜色的连续图表?更多解释:我不希望蓝线穿过红色图(请参阅附图),反之亦然,因为我只绘制一张图。我想要如图第三张图所示的图表。先感谢您。
查看完整描述

2 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

第二个建议

(请进一步阅读我的第一个建议,了解一些假设和条件)

我已经成功地建立了一种方法,它几乎应该涵盖您在这里所要求的所有内容。提供真正挑战的唯一细节是如何可视化迹线之间的间隙,因为我的第二个建议建立在为每个单独的迹线添加唯一迹线的基础上label。您可能怀疑这可能会用一堆重复的名称填充图例,但这是通过按关联标签对跟踪名称进行分组来解决的。我还建立了一个字典,您可以在其中指定每个标签的颜色。这是结果:

图 2.1 - 由标签定义的颜色

https://img1.sycdn.imooc.com//651277c8000164ec07410338.jpg

注意到灰色线了吗?这就是我之前描述的“连接性”问题的结果。您可以通过设置 中的不透明度参数(最后一个数字)来选择隐藏或显示该行color='rgba(200,200,200,0.2)'。您将在下面找到一个完整的代码片段来重现该图。有很多事情需要对整个事情进行调整,所以如果有任何不清楚的地方,请随时询问细节。

完整代码:

# imports

import plotly.express as px

import plotly.graph_objects as go

import pandas as pd

import numpy as np

import random


# settings

observations = 100

np.random.seed(5)

value = np.random.uniform(low=-1, high=1, size=observations).tolist()

time = [t for t in pd.date_range('2020', freq='D', periods=observations)]#.format()]


df=pd.DataFrame({'time': time, 

                 'value':value})

df['value']=df['value'].cumsum()

df1 = df.copy()

df1=df1.set_index('time')


# custom function to build labels as conditions of parameter values

def classify(e):

    if e > 0.75: return 'high'

    if e > 0.25: return 'medium'

    if e >= 0: return 'low'

    

# custom function to set mode = line or marker, given data length

def modes(df):

    if len(df) > 1: return 'lines'

    else: return  'markers'

    

# dictionary to specify marker or line color

# this will depend on your real world labels !!!

cols = {'high': 'green',

         'medium': 'blue',

         'low': 'red'}


df['label1'] = [(elem-df['value'].min())/(df['value'].max()-df['value'].min()) for elem in df['value']]

df['label'] = [classify(elem) for elem in df['label1']]

df = df.drop('label1', 1)


df['group'] = df['label'].ne(df['label'].shift()).cumsum()

df = df.groupby('group')

dfs = []

for name, data in df:

    dfs.append(data)


fig = go.Figure()

# one line to connect them all

fig=go.Figure((go.Scatter(x=df1.index, y=df1['value'],

                          name = 'all data',

                          line=dict(color='rgba(200,200,200,0.7)'))))


showed = []

for frame in dfs:


    if frame['label'].iloc[0] not in showed:

        

        fig.add_trace(go.Scatter(x=frame['time'], y = frame['value'],

                                 mode = modes(frame),

                                 marker_color = cols[frame['label'].iloc[0]],

                                 legendgroup=frame['label'].iloc[0],

                                 name=frame['label'].iloc[0]))

        showed.append(frame['label'].iloc[0])

    else:

        fig.add_trace(go.Scatter(x=frame['time'], y = frame['value'],

                                 mode = modes(frame),

                                  marker_color = cols[frame['label'].iloc[0]],

                                 legendgroup=frame['label'].iloc[0],

                                 name=frame['label'].iloc[0],

                                 showlegend=False

                                ))

fig.update_layout(template='plotly_dark')

fig.update_xaxes(showgrid=False)

fig.update_layout(uirevision='constant')

fig.show()

第一个建议

您应该如何执行此操作在很大程度上取决于数据集的结构。根据你的问题的声音,我只能猜测它看起来像这样:


         time     param   label

0  2020-01-01 -0.556014  medium

1  2020-01-02  0.185451    high

2  2020-01-03 -0.401111  medium

3  2020-01-04  0.436111    high

4  2020-01-05  0.412933    high

5  2020-01-06  0.636421    peak

6  2020-01-07  1.168237    peak

7  2020-01-08  1.205073    peak

8  2020-01-09  0.798674    peak

9  2020-01-10  0.174116    high

param如果是这样,那么如果您想用不同颜色的线条轨迹进行显示,您很快就会遇到数据点之间奇怪的连接问题。我想到的第一件事是将一种颜色的线条与多种颜色的标记相结合,如下所示:

https://img1.sycdn.imooc.com//651277db0001360a06430341.jpg

这将为您提供良好的交互性,您可以在其中打开和关闭所有元素,也许只研究数据中的以下部分label=='peak

https://img1.sycdn.imooc.com//651277e50001ccd106400346.jpg

让我知道这对您来说效果如何,我们可以讨论更多细节。您可以在此处找到数据样本和所有详细信息:

完整代码:

# imports

import plotly.express as px

import plotly.graph_objects as go

import pandas as pd

import numpy as np

import random


# settings

observations = 100

np.random.seed(5); cols = list('a')

param = np.random.uniform(low=-1, high=1, size=observations).tolist()

time = [t for t in pd.date_range('2020', freq='D', periods=observations).format()]


df=pd.DataFrame({'time': time, 

                 'param':param})

df['param']=df['param'].cumsum()


def classify(e):

    if e > 0.9: return 'peak'

    if e > 0.75: return 'high'

    if e > 0.25: return 'medium'

    if e > 0.9: return 'low'

    if e >= 0: return 'bottom'


df['label1'] = [(elem-df['param'].min())/(df['param'].max()-df['param'].min()) for elem in df['param']]

df['label'] = [classify(elem) for elem in df['label1']]

df = df.drop('label1', 1)


fig=go.Figure((go.Scatter(x=df['time'], y=df['param'],

                         mode='lines',

                         line=dict(color='rgba(0,0,200,0.7)'))))

fig.add_traces(px.scatter(df, x='time', y='param', color='label').data)

fig.update_layout(template='plotly_dark')

fig.update_xaxes(showgrid=False)

fig.show()


查看完整回答
反对 回复 2023-09-26
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

如果我理解正确,您正在尝试绘制具有两个不同颜色标签的单个时间序列数据。在同一个图中绘制多条线会导致一些重叠,因为它共享时间轴。

为什么不使用散点图(不连接点)?根据数据的密度,这在视觉上看起来类似于连接的直线/曲线。

您还可以尝试绘制蓝线和红线并进行一些垂直移动以减少重叠。


查看完整回答
反对 回复 2023-09-26
  • 2 回答
  • 0 关注
  • 131 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信