Plotly:将多个图形绘制为子图
Plotly: Plot multiple figures as subplots
这些资源展示了如何从单个 Pandas DataFrame 中获取数据并在 Plotly 图表上绘制不同列的子图。我有兴趣从单独的 DataFrame 创建图形并将它们绘制到与子图相同的图形中。这对 Plotly 来说可能吗?
https://plot.ly/python/subplots/
https://plot.ly/pandas/subplots/
我正在从这样的数据框中创建每个图形:
import pandas as pd
import cufflinks as cf
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
fig1 = df.iplot(kind='bar',barmode='stack',x='Type',
y=mylist,asFigure=True)
编辑:
下面是一个基于 Naren 反馈的例子:
创建数据框:
a={'catagory':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'catagory':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
该图将只显示狗的信息,而不显示鸟或猫的信息:
fig = tls.make_subplots(rows=2, cols=1)
fig1 = df1.iplot(kind='bar',barmode='stack',x='catagory',
y=['dogs','cats','birds'],asFigure=True)
fig.append_trace(fig1['data'][0], 1, 1)
fig2 = df2.iplot(kind='bar',barmode='stack',x='catagory',
y=['dogs','cats','birds'],asFigure=True)
fig.append_trace(fig2['data'][0], 2, 1)
iplot(fig)
新答案:
我们需要遍历每只动物并附加一条新的轨迹来生成你需要的东西。这将提供我希望的所需输出。
import pandas as pd
import numpy as np
import cufflinks as cf
import plotly.tools as tls
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
import random
def generate_random_color():
r = lambda: random.randint(0,255)
return '#%02X%02X%02X' % (r(),r(),r())
a={'catagory':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'catagory':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
#shared Xaxis parameter can make this graph look even better
fig = tls.make_subplots(rows=2, cols=1)
for animal in ['dogs','cats','birds']:
animal_color = generate_random_color()
fig1 = df1.iplot(kind='bar',barmode='stack',x='catagory',
y=animal,asFigure=True,showlegend=False, color = animal_color)
fig.append_trace(fig1['data'][0], 1, 1)
fig2 = df2.iplot(kind='bar',barmode='stack',x='catagory',
y=animal,asFigure=True, showlegend=False, color = animal_color)
#if we do not use the below line there will be two legend
fig2['data'][0]['showlegend'] = False
fig.append_trace(fig2['data'][0], 2, 1)
#additional bonus
#use the below command to use the bar chart three mode
# [stack, overlay, group]
#as shown below
#fig['layout']['barmode'] = 'overlay'
iplot(fig)
输出:
旧答案:
这就是解决方案
解释:
Plotly 工具具有创建子图的子图功能,您应该阅读文档以了解更多详细信息here。所以我先用袖扣制作了一张图的条形图。需要注意的一件事是袖扣创建并同时包含数据和布局。 Plotly 只会将一个布局参数作为输入,因此我只从袖扣图中获取数据参数,并将其 append_trace 传递给 make_suplots 对象。所以fig.append_trace()第二个参数是行号第三个参数是列号
import pandas as pd
import cufflinks as cf
import numpy as np
import plotly.tools as tls
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
fig = tls.make_subplots(rows=2, cols=1)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
fig1 = df.iplot(kind='bar',barmode='stack',x='A',
y='B',asFigure=True)
fig.append_trace(fig1['data'][0], 1, 1)
df2 = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('EFGH'))
fig2 = df2.iplot(kind='bar',barmode='stack',x='E',
y='F',asFigure=True)
fig.append_trace(fig2['data'][0], 2, 1)
iplot(fig)
如果你想在子图中添加一个通用布局,我建议你这样做
fig.append_trace(fig2['data'][0], 2, 1)
fig['layout']['showlegend'] = False
iplot(fig)
甚至
fig.append_trace(fig2['data'][0], 2, 1)
fig['layout'].update(fig1['layout'])
iplot(fig)
所以在绘图之前的第一个示例中,我访问了布局对象的各个参数并进行了更改,您需要查看布局对象属性以供参考。
在绘图之前的第二个示例中,我使用袖扣生成的布局更新图形的布局,这将产生与我们在袖扣中看到的相同的输出。
您还可以使用袖扣尝试以下方法:
cf.subplots([df1.figure(kind='bar',categories='category'),
df2.figure(kind='bar',categories='category')],shape=(2,1)).iplot()
这应该给你:
您可以获得一个仪表板,其中包含多个图表,每个图表旁边都有图例:
import plotly
import plotly.offline as py
import plotly.graph_objs as go
fichier_html_graphs=open("DASHBOARD.html",'w')
fichier_html_graphs.write("<html><head></head><body>"+"\n")
i=0
while 1:
if i<=40:
i=i+1
#______________________________--Plotly--______________________________________
color1 = '#00bfff'
color2 = '#ff4000'
trace1 = go.Bar(
x = ['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [25,100,20,7,38,170,200],
name='Debit',
marker=dict(
color=color1
)
)
trace2 = go.Scatter(
x=['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [3,50,20,7,38,60,100],
name='Taux',
yaxis='y2'
)
data = [trace1, trace2]
layout = go.Layout(
title= ('Chart Number: '+str(i)),
titlefont=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'
),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
yaxis=dict(
title='Bandwidth Mbit/s',
titlefont=dict(
color=color1
),
tickfont=dict(
color=color1
)
),
yaxis2=dict(
title='Ratio %',
overlaying='y',
side='right',
titlefont=dict(
color=color2
),
tickfont=dict(
color=color2
)
)
)
fig = go.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Chart_'+str(i)+'.html',auto_open=False)
fichier_html_graphs.write(" <object data=\""+'Chart_'+str(i)+'.html'+"\" width=\"650\" height=\"500\"></object>"+"\n")
else:
break
fichier_html_graphs.write("</body></html>")
print("CHECK YOUR DASHBOARD.html In the current directory")
结果:
这是一个工作示例中的一个简短函数,用于将图形列表全部保存到单个 HTML 文件中。
def figures_to_html(figs, filename="dashboard.html"):
with open(filename, 'w') as dashboard:
dashboard.write("<html><head></head><body>" + "\n")
for fig in figs:
inner_html = fig.to_html().split('<body>')[1].split('</body>')[0]
dashboard.write(inner_html)
dashboard.write("</body></html>" + "\n")
# Example figures
import plotly.express as px
gapminder = px.data.gapminder().query("country=='Canada'")
fig1 = px.line(gapminder, x="year", y="lifeExp", title='Life expectancy in Canada')
gapminder = px.data.gapminder().query("continent=='Oceania'")
fig2 = px.line(gapminder, x="year", y="lifeExp", color='country')
gapminder = px.data.gapminder().query("continent != 'Asia'")
fig3 = px.line(gapminder, x="year", y="lifeExp", color="continent",
line_group="country", hover_name="country")
figures_to_html([fig1, fig2, fig3])
您已经收到了一些非常有效的建议。然而,它们确实需要大量编码。 Facet / trellis 使用 px.bar()
的绘图将让您仅使用 (almost) 生成下面的绘图:
px.bar(df, x="category", y="dogs", facet_row="Source")
您唯一需要采取的额外步骤是引入一个变量来拆分数据,然后像这样收集或连接数据帧:
df1['Source'] = 1
df2['Source'] = 2
df = pd.concat([df1, df2])
如果您还想包括其他变量,只需执行以下操作:
fig = px.bar(df, x="category", y=["dogs", "cats", "birds"], facet_row="Source")
fig.update_layout(barmode = 'group')
完整代码:
# imports
import plotly.express as px
import pandas as pd
# data building
a={'category':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'category':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
# data processing
df1['Source'] = 1
df2['Source'] = 2
df = pd.concat([df1, df2])
# plotly figure
fig = px.bar(df, x="category", y="dogs", facet_row="Source")
fig.show()
#fig = px.bar(df, x="category", y=["dogs", "cats", "birds"], facet_row="Source")
#fig.update_layout(barmode = 'group')
这些资源展示了如何从单个 Pandas DataFrame 中获取数据并在 Plotly 图表上绘制不同列的子图。我有兴趣从单独的 DataFrame 创建图形并将它们绘制到与子图相同的图形中。这对 Plotly 来说可能吗?
https://plot.ly/python/subplots/
https://plot.ly/pandas/subplots/
我正在从这样的数据框中创建每个图形:
import pandas as pd
import cufflinks as cf
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
fig1 = df.iplot(kind='bar',barmode='stack',x='Type',
y=mylist,asFigure=True)
编辑: 下面是一个基于 Naren 反馈的例子:
创建数据框:
a={'catagory':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'catagory':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
该图将只显示狗的信息,而不显示鸟或猫的信息:
fig = tls.make_subplots(rows=2, cols=1)
fig1 = df1.iplot(kind='bar',barmode='stack',x='catagory',
y=['dogs','cats','birds'],asFigure=True)
fig.append_trace(fig1['data'][0], 1, 1)
fig2 = df2.iplot(kind='bar',barmode='stack',x='catagory',
y=['dogs','cats','birds'],asFigure=True)
fig.append_trace(fig2['data'][0], 2, 1)
iplot(fig)
新答案:
我们需要遍历每只动物并附加一条新的轨迹来生成你需要的东西。这将提供我希望的所需输出。
import pandas as pd
import numpy as np
import cufflinks as cf
import plotly.tools as tls
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
import random
def generate_random_color():
r = lambda: random.randint(0,255)
return '#%02X%02X%02X' % (r(),r(),r())
a={'catagory':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'catagory':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
#shared Xaxis parameter can make this graph look even better
fig = tls.make_subplots(rows=2, cols=1)
for animal in ['dogs','cats','birds']:
animal_color = generate_random_color()
fig1 = df1.iplot(kind='bar',barmode='stack',x='catagory',
y=animal,asFigure=True,showlegend=False, color = animal_color)
fig.append_trace(fig1['data'][0], 1, 1)
fig2 = df2.iplot(kind='bar',barmode='stack',x='catagory',
y=animal,asFigure=True, showlegend=False, color = animal_color)
#if we do not use the below line there will be two legend
fig2['data'][0]['showlegend'] = False
fig.append_trace(fig2['data'][0], 2, 1)
#additional bonus
#use the below command to use the bar chart three mode
# [stack, overlay, group]
#as shown below
#fig['layout']['barmode'] = 'overlay'
iplot(fig)
输出:
旧答案:
这就是解决方案
解释:
Plotly 工具具有创建子图的子图功能,您应该阅读文档以了解更多详细信息here。所以我先用袖扣制作了一张图的条形图。需要注意的一件事是袖扣创建并同时包含数据和布局。 Plotly 只会将一个布局参数作为输入,因此我只从袖扣图中获取数据参数,并将其 append_trace 传递给 make_suplots 对象。所以fig.append_trace()第二个参数是行号第三个参数是列号
import pandas as pd
import cufflinks as cf
import numpy as np
import plotly.tools as tls
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
fig = tls.make_subplots(rows=2, cols=1)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
fig1 = df.iplot(kind='bar',barmode='stack',x='A',
y='B',asFigure=True)
fig.append_trace(fig1['data'][0], 1, 1)
df2 = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('EFGH'))
fig2 = df2.iplot(kind='bar',barmode='stack',x='E',
y='F',asFigure=True)
fig.append_trace(fig2['data'][0], 2, 1)
iplot(fig)
如果你想在子图中添加一个通用布局,我建议你这样做
fig.append_trace(fig2['data'][0], 2, 1)
fig['layout']['showlegend'] = False
iplot(fig)
甚至
fig.append_trace(fig2['data'][0], 2, 1)
fig['layout'].update(fig1['layout'])
iplot(fig)
所以在绘图之前的第一个示例中,我访问了布局对象的各个参数并进行了更改,您需要查看布局对象属性以供参考。
在绘图之前的第二个示例中,我使用袖扣生成的布局更新图形的布局,这将产生与我们在袖扣中看到的相同的输出。
您还可以使用袖扣尝试以下方法:
cf.subplots([df1.figure(kind='bar',categories='category'),
df2.figure(kind='bar',categories='category')],shape=(2,1)).iplot()
这应该给你:
您可以获得一个仪表板,其中包含多个图表,每个图表旁边都有图例:
import plotly
import plotly.offline as py
import plotly.graph_objs as go
fichier_html_graphs=open("DASHBOARD.html",'w')
fichier_html_graphs.write("<html><head></head><body>"+"\n")
i=0
while 1:
if i<=40:
i=i+1
#______________________________--Plotly--______________________________________
color1 = '#00bfff'
color2 = '#ff4000'
trace1 = go.Bar(
x = ['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [25,100,20,7,38,170,200],
name='Debit',
marker=dict(
color=color1
)
)
trace2 = go.Scatter(
x=['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [3,50,20,7,38,60,100],
name='Taux',
yaxis='y2'
)
data = [trace1, trace2]
layout = go.Layout(
title= ('Chart Number: '+str(i)),
titlefont=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'
),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
yaxis=dict(
title='Bandwidth Mbit/s',
titlefont=dict(
color=color1
),
tickfont=dict(
color=color1
)
),
yaxis2=dict(
title='Ratio %',
overlaying='y',
side='right',
titlefont=dict(
color=color2
),
tickfont=dict(
color=color2
)
)
)
fig = go.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Chart_'+str(i)+'.html',auto_open=False)
fichier_html_graphs.write(" <object data=\""+'Chart_'+str(i)+'.html'+"\" width=\"650\" height=\"500\"></object>"+"\n")
else:
break
fichier_html_graphs.write("</body></html>")
print("CHECK YOUR DASHBOARD.html In the current directory")
结果:
这是一个工作示例中的一个简短函数,用于将图形列表全部保存到单个 HTML 文件中。
def figures_to_html(figs, filename="dashboard.html"):
with open(filename, 'w') as dashboard:
dashboard.write("<html><head></head><body>" + "\n")
for fig in figs:
inner_html = fig.to_html().split('<body>')[1].split('</body>')[0]
dashboard.write(inner_html)
dashboard.write("</body></html>" + "\n")
# Example figures
import plotly.express as px
gapminder = px.data.gapminder().query("country=='Canada'")
fig1 = px.line(gapminder, x="year", y="lifeExp", title='Life expectancy in Canada')
gapminder = px.data.gapminder().query("continent=='Oceania'")
fig2 = px.line(gapminder, x="year", y="lifeExp", color='country')
gapminder = px.data.gapminder().query("continent != 'Asia'")
fig3 = px.line(gapminder, x="year", y="lifeExp", color="continent",
line_group="country", hover_name="country")
figures_to_html([fig1, fig2, fig3])
您已经收到了一些非常有效的建议。然而,它们确实需要大量编码。 Facet / trellis 使用 px.bar()
的绘图将让您仅使用 (almost) 生成下面的绘图:
px.bar(df, x="category", y="dogs", facet_row="Source")
您唯一需要采取的额外步骤是引入一个变量来拆分数据,然后像这样收集或连接数据帧:
df1['Source'] = 1
df2['Source'] = 2
df = pd.concat([df1, df2])
如果您还想包括其他变量,只需执行以下操作:
fig = px.bar(df, x="category", y=["dogs", "cats", "birds"], facet_row="Source")
fig.update_layout(barmode = 'group')
完整代码:
# imports
import plotly.express as px
import pandas as pd
# data building
a={'category':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'category':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
# data processing
df1['Source'] = 1
df2['Source'] = 2
df = pd.concat([df1, df2])
# plotly figure
fig = px.bar(df, x="category", y="dogs", facet_row="Source")
fig.show()
#fig = px.bar(df, x="category", y=["dogs", "cats", "birds"], facet_row="Source")
#fig.update_layout(barmode = 'group')