【问题标题】:how to loop to create subplots in Plotly, where each subplot has a few curves on it?如何在 Plotly 中循环创建子图,每个子图上都有几条曲线?
【发布时间】:2020-09-25 00:14:24
【问题描述】:

我已经在嵌套循环下面编写了成功生成 21 个图表(每个国家/地区一个图表,例如 german gasaustrian gas

dfs 是一个以 21 个国家/地区名称为键,它们各自的气体存储 dfs 为值的字典

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)

现在我被要求将这 21 个图表放在一个 HTML 文件中而不更改每个图表,例如它们可以一个接一个垂直显示

我用下面的代码用 Plotly 尝试了“子图”,并修改了几次,但从来没有想要的图表,我得到了一个没有用的图表,我看不到任何值。有人可以帮助我吗?谢谢

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) 

6 月 7 日编辑:根据 jayveesea 的建议,我在 add_trace 下添加了 row 和 col 参数,代码如下但仍然有 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')

6 月 8 日编辑: 这是我现在正在运行的代码,从@jayveesea 的答案中复制而来,只修改了 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()

但我仍然有 Traceback 消息

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

【问题讨论】:

  • 您介意分享您的数据样本吗?
  • 我没有看到任何对rowcol 的子图引用,例如fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),row=1, col=1)。见here
  • @rpanai 谢谢,我刚刚编辑了我的帖子,您可以看到奥地利数据的 df 之一,我将其转换为 dict 以便能够粘贴到此处。这是你问的吗?
  • 是的,但是当您 fig.add_trace 时,您需要告诉它哪个 rowcol... 它的 jayveesea,顺便说一句 :)
  • 嗨 @jayveesea 只是给你一些反馈,我仍然不知道为什么我不能运行你的代码,但我已经通过将 2 个参数行和列移出更正了我在 6 月 7 日上面的代码go.scatter 的,正如你之前提到的。现在这个版本的代码可以工作并且我有 1 个 HTML,现在我正在努力修复图例,因为有 21 x 7 个图例全部粘在 html 的顶部而不是靠近每个子图。感谢您的帮助

标签: python loops plotly subplot


【解决方案1】:

要在 plotly 中使用子图,您需要:

  1. 使用make_subplots 来初始化指定rowcolumn 的布局
  2. 然后使用rowcol 作为fig.add_trace 的参数。注意:子图行和列从 1(非零)开始

在您的情况下,第 2 步是您卡住的地方。最初这部分缺失(第一篇文章),但现在在您的更新中,它作为参数添加到 go.Scatter。仔细查看the examples here,因为区别只是逗号和括号以及它们的位置。

澄清一下:

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=workingGasVolume_peryear, 
                         name=f'workingGasVolume{year}',
                         line=dict(width=4,dash='dash')),
              row=i+1,
              col=1)

我在处理您的代码和数据时遇到了困难,这可能是因为我不使用这样的字典,但这是一个工作示例,您的数据在 csv 中并使用 pandas。另外,我把其中一年换到了另一个国家,这样会有另一个情节。

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

【讨论】:

  • 非常感谢@jayveesea 的帮助,我以此为例,因为我需要标题 plotly.com/python/subplots/#multiple-subplots-with-titles 我刚刚编辑了我的帖子:我从字典 dfs_storage 中粘贴了 2 个 dfs
  • 对不起,不清楚您是否还有其他问题...我尝试了新数据,它也有效。
  • 谢谢,@jayveesea,1>我尝试了您的代码,但它连续给了我回溯,我修改并停用了某些行,但回溯仍在继续。 1.1>f'workingGasVolume{y}' 应该是 f'workingGasVolume{yrs}' 对吧? 1.2>then: line=dict(width=4,dash='dash') TypeError: 'dict' object is not callable, 所以我删除了这一行, 1.3>then: col=1) ^ SyntaxError: unexpected EOF while parsing 2 .> 我不明白我最新版本的代码有什么问题,它迭代“for i in range(len(countries)):”,我仔细检查了所有的逗号、缩进和括号,不明白为什么我的代码不起作用
  • 对于#1.1,是的应该是yrs,我会更正我的答案。对于#1.2 和#1.3,我的代码似乎没有被正确复制。对于 #2,您的最新版本没有正确的子图语法。 row=i,col=1 需要是 fig.add_trace 的参数,你需要 row=i+1
  • 在上面添加了进一步的说明
猜你喜欢
  • 2017-01-04
  • 2021-08-16
  • 1970-01-01
  • 2021-01-12
  • 1970-01-01
  • 2013-09-24
  • 2014-05-18
  • 1970-01-01
  • 2019-01-09
相关资源
最近更新 更多