[英]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
發電量、 Storage
和Solar Gen
量。 頻率應在輔助 Y 軸(右側),它們的 Rest 應在左側。
與其他人相比,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 軸騰出空間。 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 關於子圖的文檔。
此處顯示的示例代碼使用較低級別的 Plotly API,而不是使用便捷的包裝器,例如graph_objects
或express
。 原因是我(個人)覺得展示“幕后”發生的事情對用戶很有幫助,而不是用方便的包裝器掩蓋底層代碼邏輯。
這樣,當用戶需要修改圖形的更精細細節時,他們將對 Plotly 為底層圖形引擎(orca)構建的list
和dict
有更好的理解。
這是我的 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.