单击条形图中的条形图以生成该条形图中值的散点图
Click on a bar in bar plot to produce a scatterplot of the values in that bar
此代码生成条形图:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import plotly.graph_objects as go
classes= ['class1', 'class2', 'class3', 'class4', 'class5', 'class6', 'class7']
lens = [199, 30, 89, 59, 109, 115, 89]
nums = [145, 457, 123, 67, 35, 31, 134]
fig = go.Figure(data=[
go.Bar(name='Length', x=classes, y=lens),
go.Bar(name='Number', x=classes, y=nums),
])
# Change the bar mode
fig.update_layout(barmode='group')
fig.update_layout(title_text='Length and Number',
title_x=0.1,
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)',
bargap=0.30,
bargroupgap=0.0,
margin=dict(l=50, r=50, t=50, b=50),
xaxis_title="Score Class",
yaxis_title="Length and Number",
yaxis = dict(
tickfont = dict(size=13)),
xaxis = dict(
tickfont = dict(size=13)),)
fig.update_xaxes(showline=True, linewidth=2, linecolor='black')
fig.update_yaxes(showline=True, linewidth=2, linecolor='black')
fig.show()
输出为:
我想点击任何一个红色条,它会把我带到那个 class.
中值的散点图
我可以用这个生成散点图:
dict2 = {}
dict2['class1'] = [(2,2),(1,1),(2,3),(3,4),(5,1)]
dict2['class2'] = [(3,1),(4,4),(5,5),(6,2),(7,1)]
dict2['class3'] = [(3,2),(4,1),(5,4),(6,4),(7,1)]
dict2['class4'] = [(3,1),(4,5),(6,3),(4,3),(5,3)]
dict2['class5'] = [(1,1),(1,1),(1,2),(3,1),(4,3)]
dict2['class6'] = [(2,2),(2,1),(2,3),(5,3),(6,4)]
class1_dict = {}
class1_dict['xs'] = [i[0] for i in dict2['class1']]
class1_dict['ys'] = [i[1] for i in dict2['class1']]
plt.scatter(class1_dict['xs'],class1_dict['ys'])
plt.show()
而且我知道如何点击条形图 return 我可以像这样放入散点图中的数据框:
dict_name = {}
dict_name['classes'] = classes
dict_name['lens'] = lens
dict_name['nums'] = nums
df = pd.DataFrame.from_dict(dict_name, orient='columns')
print(df)
axs = df.hist(bins=4, picker=True)
ax = axs[0, 0]
def onpick(event):
bar = event.artist
left = bar.get_x()
right = left + bar.get_width()
col_df = df[(df.lens >= left) & (df.lens <= right)]
ax.figure.canvas.mpl_connect('pick_event', onpick)
#plt.show()
我正在尝试更改最后一段代码,因此我可以读取条形图而不是 axs = df.hist(bins=4, picker=True)
,单击后,return 一个我可以读取的数据框散点图。
所以我想我只需要以某种方式添加这两行:
axs = df.hist(bins=4, picker=True)
ax = axs[0, 0]
到我的条形图代码,使其可点击。
所以我想因为 axs
只是一个情节,这就是 fig
,我可以将这一行添加到条形图代码中,它会起作用:
fig = go.Figure(data=[
go.Bar(name='Length', x=classes, y=lens),
go.Bar(name='Number', x=classes, y=nums),
])
ax = fig[0,0]
我得到的错误是:
Traceback (most recent call last):
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 188, in _check_path_in_prop_tree
obj = obj[p]
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 732, in __getitem__
prop = BaseFigure._str_to_dict_path(prop)
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 1839, in _str_to_dict_path
ret = _str_to_dict_path_full(key_path_str)[0]
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 71, in _str_to_dict_path_full
if len(key_path_str):
TypeError: object of type 'int' has no len()
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test3.py", line 17, in <module>
ax=axs[0,0]
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 754, in __getitem__
err = _check_path_in_prop_tree(self, orig_prop, error_cast=PlotlyKeyError)
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 212, in _check_path_in_prop_tree
if prop[i][0] == "_":
TypeError: 'int' object is not subscriptable
我想这是因为第一个图使分组条形图成为一个数字,而直方图示例却成为两个图?谁能告诉我哪里出错了?
正如@JohanC 在评论中提到的,plotly
和 matplotlib
是非常不同的库。这意味着它们的对象与任何类型的 class 层次结构都不相关,并且不共享相同的属性。
因此,您不能将 matplotlib axes
对象设置为等于 plotly
图形对象。绘图图形对象与 matplotlib 图形对象不同。您可能需要留在一个库中才能实现您想要的。如果 matplotlib onpick
功能对你很重要,那么你应该留在 matplotlib 中。我相信在 matplotlib 中你可以构造 hoverevents
但它比在 plotly 中更努力,后者将 hoverevents
作为几乎所有数字的默认值。
此外,绘图不是数组,因此 fig[0,0]
没有意义。也许你打算访问 fig.data
这是一个元组意味着你可以访问 fig.data[0], fig.data[1], ... fig.data[N]
你没有指定你想以任何方式组合 plotly 和 matplotlib,所以如果你想知道如何用 Plotly 做你要求的事情,这里有一个设置那。如果这是您可以使用的东西,我很乐意解释细节。
Plotly Dash 应用程序
完整代码:
import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure()
from jupyter_dash import JupyterDash
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import json
import plotly.express as px
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
df = px.data.tips()
fig1 = px.bar(df, x="sex", y="total_bill", color='time')
fig2= px.scatter(df, x="total_bill", y="tip")
# f = fig.full_figure_for_development(warn=False)
app = JupyterDash(__name__)
app.layout = html.Div([
dcc.Graph(id = 'fig1', figure=fig1),
dcc.Graph(id = 'fig2', figure=fig2),
html.Div(className='row', children=[
html.Div([
dcc.Markdown(("""
Clickinfo:
""")),
html.Pre(id='txt_output', style=styles['pre']),
], className='three columns'),
])
])
# inspect clickdata
@app.callback(
Output('txt_output', 'children'),
[Input('fig1', 'clickData')])
def display_click_data(clickData):
if clickData is not None:
output = json.dumps({'clickinfo':clickData}
, indent = 2)
return output
# Use clickrInfo from fig1 to subset data in fig2
@app.callback(
Output('fig2', 'figure'),
[Input('fig1', 'clickData')])
def display_click_data(clickData):
if clickData is not None:
subset = clickData['points'][0]['x']
fig = px.scatter(df[df['sex'] == subset], x="total_bill", y="tip")
return fig
return fig2
app.run_server(mode='external', port = 8071, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)
此代码生成条形图:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import plotly.graph_objects as go
classes= ['class1', 'class2', 'class3', 'class4', 'class5', 'class6', 'class7']
lens = [199, 30, 89, 59, 109, 115, 89]
nums = [145, 457, 123, 67, 35, 31, 134]
fig = go.Figure(data=[
go.Bar(name='Length', x=classes, y=lens),
go.Bar(name='Number', x=classes, y=nums),
])
# Change the bar mode
fig.update_layout(barmode='group')
fig.update_layout(title_text='Length and Number',
title_x=0.1,
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)',
bargap=0.30,
bargroupgap=0.0,
margin=dict(l=50, r=50, t=50, b=50),
xaxis_title="Score Class",
yaxis_title="Length and Number",
yaxis = dict(
tickfont = dict(size=13)),
xaxis = dict(
tickfont = dict(size=13)),)
fig.update_xaxes(showline=True, linewidth=2, linecolor='black')
fig.update_yaxes(showline=True, linewidth=2, linecolor='black')
fig.show()
输出为:
我想点击任何一个红色条,它会把我带到那个 class.
中值的散点图我可以用这个生成散点图:
dict2 = {}
dict2['class1'] = [(2,2),(1,1),(2,3),(3,4),(5,1)]
dict2['class2'] = [(3,1),(4,4),(5,5),(6,2),(7,1)]
dict2['class3'] = [(3,2),(4,1),(5,4),(6,4),(7,1)]
dict2['class4'] = [(3,1),(4,5),(6,3),(4,3),(5,3)]
dict2['class5'] = [(1,1),(1,1),(1,2),(3,1),(4,3)]
dict2['class6'] = [(2,2),(2,1),(2,3),(5,3),(6,4)]
class1_dict = {}
class1_dict['xs'] = [i[0] for i in dict2['class1']]
class1_dict['ys'] = [i[1] for i in dict2['class1']]
plt.scatter(class1_dict['xs'],class1_dict['ys'])
plt.show()
而且我知道如何点击条形图 return 我可以像这样放入散点图中的数据框:
dict_name = {}
dict_name['classes'] = classes
dict_name['lens'] = lens
dict_name['nums'] = nums
df = pd.DataFrame.from_dict(dict_name, orient='columns')
print(df)
axs = df.hist(bins=4, picker=True)
ax = axs[0, 0]
def onpick(event):
bar = event.artist
left = bar.get_x()
right = left + bar.get_width()
col_df = df[(df.lens >= left) & (df.lens <= right)]
ax.figure.canvas.mpl_connect('pick_event', onpick)
#plt.show()
我正在尝试更改最后一段代码,因此我可以读取条形图而不是 axs = df.hist(bins=4, picker=True)
,单击后,return 一个我可以读取的数据框散点图。
所以我想我只需要以某种方式添加这两行:
axs = df.hist(bins=4, picker=True)
ax = axs[0, 0]
到我的条形图代码,使其可点击。
所以我想因为 axs
只是一个情节,这就是 fig
,我可以将这一行添加到条形图代码中,它会起作用:
fig = go.Figure(data=[
go.Bar(name='Length', x=classes, y=lens),
go.Bar(name='Number', x=classes, y=nums),
])
ax = fig[0,0]
我得到的错误是:
Traceback (most recent call last):
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 188, in _check_path_in_prop_tree
obj = obj[p]
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 732, in __getitem__
prop = BaseFigure._str_to_dict_path(prop)
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 1839, in _str_to_dict_path
ret = _str_to_dict_path_full(key_path_str)[0]
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 71, in _str_to_dict_path_full
if len(key_path_str):
TypeError: object of type 'int' has no len()
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test3.py", line 17, in <module>
ax=axs[0,0]
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 754, in __getitem__
err = _check_path_in_prop_tree(self, orig_prop, error_cast=PlotlyKeyError)
File "/Users/slowatkela/anaconda/lib/python3.7/site-packages/plotly/basedatatypes.py", line 212, in _check_path_in_prop_tree
if prop[i][0] == "_":
TypeError: 'int' object is not subscriptable
我想这是因为第一个图使分组条形图成为一个数字,而直方图示例却成为两个图?谁能告诉我哪里出错了?
正如@JohanC 在评论中提到的,plotly
和 matplotlib
是非常不同的库。这意味着它们的对象与任何类型的 class 层次结构都不相关,并且不共享相同的属性。
因此,您不能将 matplotlib axes
对象设置为等于 plotly
图形对象。绘图图形对象与 matplotlib 图形对象不同。您可能需要留在一个库中才能实现您想要的。如果 matplotlib onpick
功能对你很重要,那么你应该留在 matplotlib 中。我相信在 matplotlib 中你可以构造 hoverevents
但它比在 plotly 中更努力,后者将 hoverevents
作为几乎所有数字的默认值。
此外,绘图不是数组,因此 fig[0,0]
没有意义。也许你打算访问 fig.data
这是一个元组意味着你可以访问 fig.data[0], fig.data[1], ... fig.data[N]
你没有指定你想以任何方式组合 plotly 和 matplotlib,所以如果你想知道如何用 Plotly 做你要求的事情,这里有一个设置那。如果这是您可以使用的东西,我很乐意解释细节。
Plotly Dash 应用程序
完整代码:
import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure()
from jupyter_dash import JupyterDash
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import json
import plotly.express as px
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
df = px.data.tips()
fig1 = px.bar(df, x="sex", y="total_bill", color='time')
fig2= px.scatter(df, x="total_bill", y="tip")
# f = fig.full_figure_for_development(warn=False)
app = JupyterDash(__name__)
app.layout = html.Div([
dcc.Graph(id = 'fig1', figure=fig1),
dcc.Graph(id = 'fig2', figure=fig2),
html.Div(className='row', children=[
html.Div([
dcc.Markdown(("""
Clickinfo:
""")),
html.Pre(id='txt_output', style=styles['pre']),
], className='three columns'),
])
])
# inspect clickdata
@app.callback(
Output('txt_output', 'children'),
[Input('fig1', 'clickData')])
def display_click_data(clickData):
if clickData is not None:
output = json.dumps({'clickinfo':clickData}
, indent = 2)
return output
# Use clickrInfo from fig1 to subset data in fig2
@app.callback(
Output('fig2', 'figure'),
[Input('fig1', 'clickData')])
def display_click_data(clickData):
if clickData is not None:
subset = clickData['points'][0]['x']
fig = px.scatter(df[df['sex'] == subset], x="total_bill", y="tip")
return fig
return fig2
app.run_server(mode='external', port = 8071, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)