简体   繁体   English

Plotly:如何添加多个 y 轴?

[英]Plotly: How to add multiple y-axes?

I have data with 5 different columns and their value varies from each other.我有 5 个不同列的数据,它们的值彼此不同。

Actual gen  Storage Solar Gen   Total Gen   Frequency
  1464      1838    1804         18266        51 
  2330      2262    518          4900         51
  2195      923     919          8732         49
  2036      1249    1316         3438         48
  2910      534     1212         4271         47
  857       2452    1272         6466         50
  2331      990     2729         14083        51
  2604      767     2730         19037        47
  993       2606    705          17314        51
  2542      213     548          10584        52
  2030      942     304          11578        52
  562       414     2870         840          52
  1111      1323    337          19612        49   
  1863      2498    1992         18941        48
  1575      2262    1576         3322         48
  1223      657     661          10292        47
  1850      1920    2986         10130        48
  2786      1119    933          2680         52
  2333      1245    1909         14116        48
  1606      2934    1547         13767        51

So in from this data I want to plot a graph with 3 y-axis.所以从这个数据中我想 plot 一个带有 3 个 y 轴的图。 One for the frequency , second for the Total Gen and third is for Actual gen , Storage and Solar Gen .一个是frequency ,第二个是Total Gen发电量,第三个是Actual gen发电量、 StorageSolar Gen量。 Frequency should be on the secondary Y-axis(Right side) and the Rest of them should be on the left side.频率应在辅助 Y 轴(右侧),它们的 Rest 应在左侧。

  • For frequency as you can see the values are very random between 47 to 52 that's why it should be on the right side, like this:对于频率,您可以看到值在 47 到 52 之间非常随机,这就是为什么它应该在右侧,如下所示: 在此处输入图像描述

  • For Total Gen value are very high as compared to others as they are from 100-20000 so that's I can't merge them with others, something like this:与其他人相比,Total Gen 值非常高,因为它们在 100-20000 之间,所以我无法将它们与其他人合并,如下所示: 在此处输入图像描述 Here I want:在这里我想要:

  • Y-axis title 1 = Actual gen, Storage, and Solar gen Y 轴标题 1 = 实际发电、存储和太阳能发电

  • Y-axis title 2 = Total gen Y 轴标题 2 = 总代

  • Y-axis title 3 = Frequency Y 轴标题 3 = 频率

My approach:我的做法:

import logging

import pandas as pd
import plotly.graph_objs as go
import plotly.offline as pyo
import xlwings as xw
from plotly.subplots import make_subplots

app = xw.App(visible=False)
try:
    wb = app.books.open('2020 10 08 0000 (Float).xlsx')
    sheet = wb.sheets[0]
    
    actual_gen = sheet.range('A2:A21').value
    frequency = sheet.range('E2:E21').value
    storage = sheet.range('B2:B21').value
    total_gen = sheet.range('D2:D21').value
    solar_gen = sheet.range('C2:C21').value

except Exception as e:
    logging.exception("Something awful happened!")
    print(e)
finally:
    app.quit()
    app.kill()

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces
fig.add_trace(
    go.Scatter(y=storage, name="BESS(KW)"),
)
fig.add_trace(
    go.Scatter(y=actual_gen, name="Act(KW)"),
)
fig.add_trace(
    go.Scatter(y=solar_gen, name="Solar Gen")
)
fig.add_trace(
    go.Scatter(x=x_values, y=total_gen, name="Total Gen",yaxis = 'y2')
)
fig.add_trace(
    go.Scatter(y=frequency, name="Frequency",yaxis = 'y1'),
)

fig.update_layout( title_text = '8th oct BESS',
    yaxis2=dict(title="BESS(KW)",titlefont=dict(color="red"), tickfont=dict(color="red")),
    yaxis3=dict(title="Actual Gen(KW)",titlefont=dict(color="orange"),tickfont=dict(color="orange"), anchor="free", overlaying="y2", side="left"),
    yaxis4=dict(title="Solar Gen(KW)",titlefont=dict(color="pink"),tickfont=dict(color="pink"), anchor="x2",overlaying="y2", side="left"),
    yaxis5=dict(title="Total Gen(KW)",titlefont=dict(color="cyan"),tickfont=dict(color="cyan"), anchor="free",overlaying="y2", side="left"),
    yaxis6=dict(title="Frequency",titlefont=dict(color="purple"),tickfont=dict(color="purple"), anchor="free",overlaying="y2", side="right"))

fig.show()

Can someone please help?有人可以帮忙吗?

Here is an example of how multi-level y-axes can be created.这是一个如何创建多级 y 轴的示例。

Essentially, the keys to this are:本质上,关键是:

  • Create a key in the layout dict, for each axis, then assign a trace to the that axis.layout字典中为每个轴创建一个键,然后为该轴分配一条轨迹。
  • Set the xaxis domain to be narrower than [0, 1] (for example [0.2, 1] ), thus pushing the left edge of the graph to the right, making room for the multi-level y-axis.xaxis domain设置为比[0, 1]窄(例如[0.2, 1] ),从而将图形的左边缘向右推,为多级 y 轴腾出空间。

A link to the official Plotly docs on the subject.关于该主题的官方 Plotly 文档的链接。

To make reading the data easier for this demonstration, I have taken the liberty of storing your dataset as a CSV file, rather than Excel - then used the pandas.read_csv() function to load the dataset into a pandas.DataFrame , which is then passed into the plotting functions as data columns. To make reading the data easier for this demonstration, I have taken the liberty of storing your dataset as a CSV file, rather than Excel - then used the pandas.read_csv() function to load the dataset into a pandas.DataFrame , which is then作为数据列传递给绘图函数。

Example:例子:

Read the dataset:读取数据集:

df = pd.read_csv('energy.csv')

Sample plotting code:示例绘图代码:

layout = {'title': '8th Oct BESS'}
traces = []

traces.append({'y': df['storage'], 'name': 'Storage'})
traces.append({'y': df['actual_gen'], 'name': 'Actual Gen'})
traces.append({'y': df['solar_gen'], 'name': 'Solar Gen'})
traces.append({'y': df['total_gen'], 'name': 'Total Gen', 'yaxis': 'y2'})
traces.append({'y': df['frequency'], 'name': 'Frequency', 'yaxis': 'y3'})

layout['xaxis'] = {'domain': [0.12, 0.95]}
layout['yaxis1'] = {'title': 'Actual Gen, Storage, Solar Gen', 'titlefont': {'color': 'orange'}, 'tickfont': {'color': 'orange'}}
layout['yaxis2'] = {'title': 'Total Gen', 'side': 'left', 'overlaying': 'y', 'anchor': 'free', 'titlefont': {'color': 'red'}, 'tickfont': {'color': 'red'}}
layout['yaxis3'] = {'title': 'Frequency', 'side': 'right', 'overlaying': 'y', 'anchor': 'x', 'titlefont': {'color': 'purple'}, 'tickfont': {'color': 'purple'}}
    
pio.show({'data': traces, 'layout': layout})

Graph:图形:

Given the nature of these traces, they overlay each other heavily, which could make graph interpretation difficult.鉴于这些痕迹的性质,它们相互重叠,这可能使图形解释变得困难。

A couple of options are available:有几个选项可用:

  • Change the range parameter for each y-axis so the axis only occupies a portion of the graph.更改每个 y 轴的range参数,使轴仅占据图形的一部分。 For example, if a dataset ranges from 0-5, set the corresponding yaxis range parameter to [-15, 5] , which will push that trace near the top of the graph.例如,如果数据集的范围为 0-5,则将相应的yaxis range参数设置为[-15, 5] ,这会将轨迹推到靠近图表顶部的位置。

  • Consider using subplots, where like-traces can be grouped... or each trace can have it's own graph.考虑使用子图,其中可以对相似的轨迹进行分组……或者每个轨迹都可以有自己的图形。 Here are Plotly's docs on subplots.这是 Plotly 关于子图的文档。

在此处输入图像描述

Comments (TL;DR):评论(TL;DR):

The example code shown here uses the lower-level Plotly API, rather than a convenience wrapper such as graph_objects or express .此处显示的示例代码使用较低级别的 Plotly API,而不是使用便捷的包装器,例如graph_objectsexpress The reason is that I (personally) feel it's helpful to users to show what is occurring 'under the hood', rather than masking the underlying code logic with a convenience wrapper.原因是我(个人)觉得展示“幕后”发生的事情对用户很有帮助,而不是用方便的包装器掩盖底层代码逻辑。

This way, when the user needs to modify a finer detail of the graph, they will have a better understanding of the list s and dict s which Plotly is constructing for the underlying graphing engine (orca).这样,当用户需要修改图形的更精细细节时,他们将对 Plotly 为底层图形引擎(orca)构建的listdict有更好的理解。

This is my function to plot any dataframe with index as x in the x axis.这是我的 function 到 plot 任何 dataframe,x 轴上的索引为 x。 Should support any size of dataframes应该支持任何大小的数据框

def plotly_multi(data):
    if data.shape[1]>2:
        fig = go.Figure()
        fig.add_trace(
            go.Scatter(x=data.index, y=data.iloc[:, 0], name=data.columns[0]))
    
        fig.update_layout(
            xaxis=dict(domain=[0.1, 0.9]),
            yaxis=dict(title=data.columns[0]),
            yaxis2=dict(title=data.columns[1], anchor="x", overlaying="y", side="right"))
    
        for i, col in enumerate(data.columns[1:], 1):
            fig.add_trace(
                go.Scatter(x=data.index,y=data[col],name=col,yaxis=f"y{i+1}"))
    
        for i, col in enumerate(data.columns[2:], 2):
            axis = f"yaxis{i+1}"
    
            if i%2 == 0:
                side = "left"
                position = (i-1)*0.05
            else:
                side = "right"
                position = 1 - (i-2)*0.05
    
            axis_value = dict(
                title=col,
                anchor="free",
                overlaying="y",
                side=side,
                position=position)
            exec(f"fig.update_layout({axis} = axis_value)")
    if data.shape[1]==2:
        fig = make_subplots(specs=[[{"secondary_y": True}]])
        # Add traces
        fig.add_trace(
            go.Scatter(x=data.index, y=data.iloc[:, 0], name=data.columns[0]),
            secondary_y=False,)
        fig.add_trace(
            go.Scatter(x=data.index, y=data.iloc[:, 1], name=data.columns[1]),
            secondary_y=True,)
        # Set x-axis title
        fig.update_xaxes(title_text="Date")
        # Set y-axes titles
        fig.update_yaxes(title_text=data.columns[0], secondary_y=False)
        fig.update_yaxes(title_text=data.columns[0], secondary_y=True)
    if data.shape[1] == 1:
        fig = px.line(data.reset_index(), x = data.index.name, y = data.columns)
    
    fig.update_layout(
    title_text="Data",
    width=800,)
    
    fig.show()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM