如何在 Plotly 中循环创建子图,每个子图上都有几条曲线?
问题描述
我已经在下面编写了嵌套循环以成功生成 21 个图表(每个国家/地区一个图表,例如
I already wrote below nested loops to generate 21 charts with success (one chart for each country, for example german gas austrian gas)
dfs is a dict with 21 countries names as keys and their respective gas storage dfs as values
for country in list(dfs_storage.keys()):
df_country=dfs_storage[country]
month = list(set(df_country['month']))
fig = go.Figure()
for year in set(df_country['year']):
workingGasVolume_peryear=df_country.loc[df_country['year']==year,'workingGasVolume']
gasInStorage_peryear=df_country.loc[df_country['year']==year,'gasInStorage']
# Create and style traces
fig.add_trace(go.Scatter(x=month, y=workingGasVolume_peryear, name=f'workingGasVolume{year}',
line=dict(width=4,dash='dash')))
fig.add_trace(go.Scatter(x=month, y=gasInStorage_peryear, name=f'gasInStorage{year}',
line = dict(width=4)))
# Edit the layout
fig.update_layout(title=f'{country} workingGasVolume gasInStorage',
xaxis_title='Month',
yaxis_title='Gas Volume')
offline.plot({'data':fig},filename=f'{country} gas storage.html',auto_open=False)
Now I am asked to put these 21 charts in one HTML file without changing each chart, they can appear vertically one after another for example
I tried the "subplots" with Plotly with below code and modified a few times but never have the desired chart, I got one single useless chart where I can't see any values.. Can anyone help me? Thanks
countries=[]
for country in list(dfs_storage.keys()):
countries.append(country)
fig = make_subplots(
rows=len(list(dfs_storage.keys())),cols=1,
subplot_titles=(countries))
for country in countries:
df_country=dfs_storage[country]
month = list(set(df_country['month']))
for year in set(df_country['year']):
workingGasVolume_peryear=df_country.loc[df_country['year']==year,'workingGasVolume']
gasInStorage_peryear=df_country.loc[df_country['year']==year,'gasInStorage']
# Create and style traces
fig.add_trace(go.Scatter(x=month, y=workingGasVolume_peryear, name=f'workingGasVolume{year}',
line=dict(width=4,dash='dash')))
fig.add_trace(go.Scatter(x=month, y=gasInStorage_peryear, name=f'gasInStorage{year}',
line = dict(width=4)))
# Edit the layout
# fig.update_layout(title='workingGasVolume gasInStorage',
# xaxis_title='Month',
# yaxis_title='Gas Volume')
offline.plot({'data':fig},filename='gas storage.html',auto_open=False)
Edit 7th June: as per jayveesea's advice, I added the row and col argument under add_trace, the code is below but still has Traceback:
countries=[]
for country in list(dfs_storage.keys()):
countries.append(country)
fig = make_subplots(
rows=len(list(dfs_storage.keys())),cols=1,
subplot_titles=(countries))
for i in range(len(countries)):
country=countries[i]
df_country=dfs_storage[country]
month = list(set(df_country['month']))
for year in set(df_country['year']):
workingGasVolume_peryear=df_country.loc[df_country['year']==year,'workingGasVolume']
gasInStorage_peryear=df_country.loc[df_country['year']==year,'gasInStorage']
# Create and style traces
fig.add_trace(go.Scatter(x=month, y=workingGasVolume_peryear, name=f'workingGasVolume{year}',row=i,col=1,
line=dict(width=4,dash='dash')))
fig.add_trace(go.Scatter(x=month, y=gasInStorage_peryear, name=f'gasInStorage{year}',row=i,col=1,
line = dict(width=4)))
# Edit the layout
# fig.update_layout(title='workingGasVolume gasInStorage',
# xaxis_title='Month',
# yaxis_title='Gas Volume')
offline.plot({'data':fig},filename='gas storage.html',auto_open=False)
print('the Plotly charts are saved in the same folder as the Python code')
Edit 8th June: This is the code I am running now, copied from @jayveesea's answer and only modified the name of the df
countries=[]
for country in list(dfs_storage.keys()):
countries.append(country)
# STEP 1
fig = make_subplots(
rows=len(countries), cols=1,
subplot_titles=(countries))
for i, country in enumerate(countries): #enumerate here to get access to i
years = df_country.year[df_country.country==country].unique()
for yrs in years:
focus = (df_country.country==country) & (df_country.year==yrs)
month = df_country.month[focus]
workingGasVolume_peryear = df_country.workingGasVolume[focus]
gasInStorage_peryear = df_country.gasInStorage[focus]
# STEP 2, notice position of arguments!
fig.add_trace(go.Scatter(x=month,
y=workingGasVolume_peryear,
name=f'workingGasVolume{yrs}',
line=dict(width=4,dash='dash')),
row=i+1, #index for the subplot, i+1 because plotly starts with 1
col=1)
fig.add_trace(go.Scatter(x=month,
y=gasInStorage_peryear,
name=f'gasInStorage{yrs}',
line = dict(width=4)),
row=i+1,
col=1)
fig.show()
Yet I still have Traceback message
Traceback (most recent call last):
File "<ipython-input-27-513826172e49>", line 43, in <module>
line=dict(width=4,dash='dash')),
TypeError: 'dict' object is not callable
解决方案
To use subplots in plotly you need to:
- use
make_subplots
to initialize the layout specifying therow
andcolumn
- then use
row
andcol
as arguments tofig.add_trace
. NOTE: subplots row and columns start at 1 (not zero)
In your case, step2 is where you are getting stuck. Initially this part was missing (first post), but now in your update it's added in as an argument to go.Scatter
. Carefully look over the examples here as the differences are just commas and parentheses and their placement.
To clarify, this:
fig.add_trace(go.Scatter(x=month,
y=workingGasVolume_peryear,
name=f'workingGasVolume{year}',
row=i,
col=1,
line=dict(width=4,dash='dash')))
should be:
fig.add_trace(go.Scatter(x=month,
y=workingGasVolume_peryear,
name=f'workingGasVolume{year}',
line=dict(width=4,dash='dash')),
row=i+1,
col=1)
I'm having difficulty with your code and data, which could be on my end as I do not use dictionaries like this, but here is a working example with your data in a csv and the use of pandas
. Also, I changed one of the years to a different country so that there would be another plot.
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_csv('someData.csv')
countries = df.country.unique()
# STEP 1
fig = make_subplots(
rows=len(countries), cols=1,
subplot_titles=(countries))
for i, country in enumerate(countries): #enumerate here to get access to i
years = df.year[df.country==country].unique()
for yrs in years:
focus = (df.country==country) & (df.year==yrs)
month = df.month[focus]
workingGasVolume_peryear = df.workingGasVolume[focus]
gasInStorage_peryear = df.gasInStorage[focus]
# STEP 2, notice position of arguments!
fig.add_trace(go.Scatter(x=month,
y=workingGasVolume_peryear,
name=f'workingGasVolume{yrs}',
line=dict(width=4,dash='dash')
),
row=i+1, #index for the subplot, i+1 because plotly starts with 1
col=1)
fig.add_trace(go.Scatter(x=month,
y=gasInStorage_peryear,
name=f'gasInStorage{yrs}',
line = dict(width=4)),
row=i+1,
col=1)
fig.show()
相关文章