簡體   English   中英

Plotly:如何添加多個 y 軸?

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

我有 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

所以從這個數據中我想 plot 一個帶有 3 個 y 軸的圖。 一個是frequency ,第二個是Total Gen發電量,第三個是Actual gen發電量、 StorageSolar Gen量。 頻率應在輔助 Y 軸(右側),它們的 Rest 應在左側。

  • 對於頻率,您可以看到值在 47 到 52 之間非常隨機,這就是為什么它應該在右側,如下所示: 在此處輸入圖像描述

  • 與其他人相比,Total Gen 值非常高,因為它們在 100-20000 之間,所以我無法將它們與其他人合並,如下所示: 在此處輸入圖像描述 在這里我想要:

  • Y 軸標題 1 = 實際發電、存儲和太陽能發電

  • Y 軸標題 2 = 總代

  • Y 軸標題 3 = 頻率

我的做法:

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()

有人可以幫忙嗎?

這是一個如何創建多級 y 軸的示例。

本質上,關鍵是:

  • layout字典中為每個軸創建一個鍵,然后為該軸分配一條軌跡。
  • xaxis domain設置為比[0, 1]窄(例如[0.2, 1] ),從而將圖形的左邊緣向右推,為多級 y 軸騰出空間。

關於該主題的官方 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作為數據列傳遞給繪圖函數。

例子:

讀取數據集:

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

示例繪圖代碼:

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})

圖形:

鑒於這些痕跡的性質,它們相互重疊,這可能使圖形解釋變得困難。

有幾個選項可用:

  • 更改每個 y 軸的range參數,使軸僅占據圖形的一部分。 例如,如果數據集的范圍為 0-5,則將相應的yaxis range參數設置為[-15, 5] ,這會將軌跡推到靠近圖表頂部的位置。

  • 考慮使用子圖,其中可以對相似的軌跡進行分組……或者每個軌跡都可以有自己的圖形。 這是 Plotly 關於子圖的文檔。

在此處輸入圖像描述

評論(TL;DR):

此處顯示的示例代碼使用較低級別的 Plotly API,而不是使用便捷的包裝器,例如graph_objectsexpress 原因是我(個人)覺得展示“幕后”發生的事情對用戶很有幫助,而不是用方便的包裝器掩蓋底層代碼邏輯。

這樣,當用戶需要修改圖形的更精細細節時,他們將對 Plotly 為底層圖形引擎(orca)構建的listdict有更好的理解。

這是我的 function 到 plot 任何 dataframe,x 軸上的索引為 x。 應該支持任何大小的數據框

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