[英]Plotly: How to combine make_subplots() and ff.create_distplot()?
使用 plotly 创建多个子图既简单又优雅。 考虑以下示例,该示例并排绘制来自 dataframe 的两个系列:
Plot:
代码:
# imports
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# data
np.random.seed(123)
frame_rows = 40
n_plots = 6
#frame_columns = ['V_'+str(e) for e in list(range(1,n_plots+1))]
frame_columns = ['V_1', 'V_2']
df = pd.DataFrame(np.random.uniform(-10,10,size=(frame_rows, len(frame_columns))),
index=pd.date_range('1/1/2020', periods=frame_rows),
columns=frame_columns)
df=df.cumsum()+100
df.iloc[0]=100
# plotly setup
plot_rows=1
plot_cols=2
fig = make_subplots(rows=plot_rows, cols=plot_cols)
# plotly traces
fig.add_trace(go.Scatter(x=df.index, y=df['V_1']), row=1, col=1)
fig.add_trace(go.Scatter(x=df.index, y=df['V_2']), row=1, col=2)
fig.show()
用类似的对象替换go.Scatter()
object 很容易:
Plot:
但我似乎找不到将此设置与ff.create_distplot()
结合起来的方法:
分布图:
带有 distplot 的代码:
# imports
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# data
np.random.seed(123)
frame_rows = 40
n_plots = 6
#frame_columns = ['V_'+str(e) for e in list(range(1,n_plots+1))]
frame_columns = ['V_1', 'V_2']
df = pd.DataFrame(np.random.uniform(-10,10,size=(frame_rows, len(frame_columns))),
index=pd.date_range('1/1/2020', periods=frame_rows),
columns=frame_columns)
df=df.cumsum()+100
df.iloc[0]=100
# plotly setup
plot_rows=1
plot_cols=2
fig = make_subplots(rows=plot_rows, cols=plot_cols)
# plotly traces
fig.add_trace(go.Scatter(x=df.index, y=df['V_1']), row=1, col=1)
#fig.add_trace(go.Scatter(x=df.index, y=df['V_2']), row=1, col=2)
# distplot
hist_data = [df['V_1'].values, df['V_2'].values]
group_labels = ['Group 1', 'Group 2']
#fig2 = ff.create_distplot(hist_data, group_labels)
# combine make_subplots, go.Scatter and ff.create_distplot(
fig.add_trace(ff.create_distplot(hist_data, group_labels), row=1, col=2)
fig.show()
这会引发一个相当大的 ValueError。
原因似乎是go.Scatter()
和ff.create_distplot()
返回两种不同的数据类型; plotly.graph_objs.Scatter
和plotly.graph_objs._figure.Figure
,分别。 并且它肯定似乎make_subplots
不适用于后者。 或者有人知道解决这个问题的方法吗?
感谢您的任何建议!
事实证明,您不能直接执行此操作,因为make_subplots()
不会直接接受plotly.graph_objs._figure.Figure
object 作为add_trace()
的参数。 但是您可以构建一个ff.create_distplot
'并从该图中“窃取”数据并将它们应用到go.Histogram
和go.Scatter()
中接受的对象的组合中make_subplots()
。 你甚至可以用地毯/边距 plot 做同样的事情。
Plot:
代码:
# imports
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# data
np.random.seed(123)
frame_rows = 40
n_plots = 6
#frame_columns = ['V_'+str(e) for e in list(range(1,n_plots+1))]
frame_columns = ['V_1', 'V_2']
df = pd.DataFrame(np.random.uniform(-10,10,size=(frame_rows, len(frame_columns))),
index=pd.date_range('1/1/2020', periods=frame_rows),
columns=frame_columns)
df=df.cumsum()+100
df.iloc[0]=100
# plotly setup
plot_rows=2
plot_cols=2
fig = make_subplots(rows=plot_rows, cols=plot_cols)
# plotly traces
fig.add_trace(go.Scatter(x=df.index, y=df['V_1']), row=1, col=1)
fig.add_trace(go.Scatter(x=df.index, y=df['V_2']), row=2, col=1)
# distplot
hist_data = [df['V_1'].values, df['V_2'].values]
group_labels = ['Group 1', 'Group 2']
fig2 = ff.create_distplot(hist_data, group_labels)
fig.add_trace(go.Histogram(fig2['data'][0],
marker_color='blue'
), row=1, col=2)
fig.add_trace(go.Histogram(fig2['data'][1],
marker_color='red'
), row=1, col=2)
fig.add_trace(go.Scatter(fig2['data'][2],
line=dict(color='blue', width=0.5)
), row=1, col=2)
fig.add_trace(go.Scatter(fig2['data'][3],
line=dict(color='red', width=0.5)
), row=1, col=2)
# rug / margin plot to immitate ff.create_distplot
df['rug 1'] = 1.1
df['rug 2'] = 1
fig.add_trace(go.Scatter(x=df['V_1'], y = df['rug 1'],
mode = 'markers',
marker=dict(color = 'blue', symbol='line-ns-open')
), row=2, col=2)
fig.add_trace(go.Scatter(x=df['V_2'], y = df['rug 2'],
mode = 'markers',
marker=dict(color = 'red', symbol='line-ns-open')
), row=2, col=2)
# some manual adjustments on the rugplot
fig.update_yaxes(range=[0.95,1.15], tickfont=dict(color='rgba(0,0,0,0)', size=14), row=2, col=2)
fig.update_layout(showlegend=False)
fig.show()
对@vestland 解决方案的进一步建议是使用select_traces
并迭代地组合您的新图形。 因此,您可以使用以下方法重新分配它们,而不是使用图中的数据重新绘制轨迹:
dist_fig = ff.create_distplot(hist_data=hist_data, group_labels=group_labels)
for trace in dist_fig.select_traces():
fig.add_trace(trace, row=1, col=2)
这样您就不需要检查数据字段的确切索引值。 所以将新方法翻译成你的代码,它会是这样的:
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# data
np.random.seed(123)
frame_rows = 40
n_plots = 6
frame_columns = ['V_1', 'V_2']
df = pd.DataFrame(np.random.uniform(-10, 10, size=(frame_rows, len(frame_columns))),
index=pd.date_range('1/1/2020', periods=frame_rows),
columns=frame_columns)
df = df.cumsum() + 100
df.iloc[0] = 100
# plotly setup
plot_rows = 2
plot_cols = 2
fig = make_subplots(rows=plot_rows, cols=plot_cols)
# plotly traces
fig.add_trace(go.Scatter(x=df.index, y=df['V_1']), row=1, col=1)
fig.add_trace(go.Scatter(x=df.index, y=df['V_2']), row=2, col=1)
# distplot
hist_data = [df[col_name].to_list() for col_name in frame_columns]
dist_fig = ff.create_distplot(hist_data=hist_data, group_labels=frame_columns)
for trace in dist_fig.select_traces():
fig.add_trace(trace, row=1, col=2)
df['rug 1'] = 1.1
df['rug 2'] = 1
fig.add_trace(go.Scatter(x=df['V_1'], y = df['rug 1'],
mode = 'markers',
marker=dict(color = 'blue', symbol='line-ns-open')
), row=2, col=2)
fig.add_trace(go.Scatter(x=df['V_2'], y = df['rug 2'],
mode = 'markers',
marker=dict(color = 'orange', symbol='line-ns-open')
), row=2, col=2)
fig.show()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.