【发布时间】:2021-10-19 20:10:33
【问题描述】:
我正在尝试使用 plotly 与 ipywidgets 制作交互式情节,但恐怕我没有得到任何东西。 我有一些带有坐标和一些列的数据框。我想在散点图中绘制数据框,以便 coord1=x, coord2=y 并且每个标记点都由交互选择的列选择的列的值着色。
此外,我希望当我使用交互式菜单更改列值时,每个点的颜色都会更改为我选择的列,并根据新的最小值和最大值重新调整颜色条的最小值和最大值柱子。 此外,当我更改另一个选择器(selector2)时,我希望绘图仅显示与某个 colID big_grid [big_grid [“id_col”] == selector2.value] 匹配的mu 数据帧的子集。 最后应该有一个范围滑块小部件来调整颜色栏的颜色范围
所以现在我有了这个
big_grid=pd.DataFrame(data=dict(id_col=[1,2,3,4,5],
col1=[0.1,0.2,0.3,0.4,0.5],
col2=[10,20,30,40,50],
coord1=[6,7,8,9,10],
coord2=[6,7,8,9,10]))
list_elem=["col1","col2"]
list_id=big_grid.id_col.values
dropm_elem=widgets.Dropdown(options=list(list_elem))
dropm_id=widgets.SelectMultiple(
options=list_id,
description="Active",
disabled=False
)
rangewidg=widgets.FloatRangeSlider(value=[big_grid[dropm_elem.value].min(),big_grid[dropm_elem.value].max()],
min=big_grid[dropm_elem.value].min(),
max=big_grid[dropm_elem.value].max(),
step=0.001,
readout_format='.3f',
description="Color Range",
continuous_update=False)
fig = go.FigureWidget(data=px.scatter(big_grid,
x="coord1",
y="coord2",
color=big_grid[dropm_elem.value],
color_continuous_scale="Turbo",)
)
def handle_id_change(change):
fig.data[0]['x']=big_grid[big_grid['id_col'].isin(dropm_id.value)]["coord1"]
fig.data[0]['y']=big_grid[big_grid['id_col'].isin(dropm_id.value)]["coord2"]
fig.data[0]['marker']['color']=big_grid[big_grid['id_col'].isin(dropm_id.value)][dropm_elem.value]
fig.data[0]['marker']['cmin']=big_grid[big_grid['id_col'].isin(dropm_id.value)][dropm_elem.value].min()
fig.data[0]['marker']['cmax']=big_grid[big_grid['id_col'].isin(dropm_id.value)][dropm_elem.value].max()
def handle_elem_change(change):
fig.data[0]['marker']['color']=big_grid[big_grid['id_col'].isin(dropm_id.value)][dropm_elem.value]
dropm_elem.observe(handle_elem_change,names='value')
dropm_id.observe(handle_id_change,names='value')
right_box1 =widgets.HBox([fig])
right_box2=widgets.VBox([dropm_elem,dropm_id,rangewidg])
box=widgets.HBox([right_box1,right_box2])
box
因此,像这样选择子集(来自 dropm_id)是有效的,但是 rangewidget 和悬停被破坏了。基本上,当我更改 dromp_elem 时,颜色不会像我预期的那样调整,而是变暗且均匀。同时,如果您更改列并将鼠标悬停在点上,它会列出 col2 的值,但标签仍然显示 col1。
我担心我的生活过于复杂,肯定有更简单的方法,有人可以启发我吗?
编辑:如果我使用不同的方法并使用全局变量来定义要绘制的子集、绘图函数和 widget.interact 函数,我可以使其工作。问题是在这种情况下,绘图不是小部件,所以我不能将它放入 VBox 或 HBox。 它也仍然感觉不对,使用全局变量不是很好的做法。无论如何我都会提供代码以供参考:
def plot(elem,rang):
fig = px.scatter(subset, x="coord1", y="coord2", color=elem,color_continuous_scale="Turbo",range_color=rang)
fig.show()
def handle_elem_change(change):
with rangewidg.hold_trait_notifications(): #This is because if you do't put it it set max,
rangewidg.max=big_grid[dropm_elem.value].max() #and if max is < min he freaks out. Like this he first
rangewidg.min=big_grid[dropm_elem.value].min() #set everything and then send the eventual errors notification.
rangewidg.value=[big_grid[dropm_elem.value].min(),big_grid[dropm_elem.value].max()]
def handle_id_change(change):
global subset
subset=big_grid[big_grid['id_col'].isin(dropm_id.value)]
big_grid=pd.DataFrame(data=dict(id_col=[1,2,3,4,5],
col1=[0.1,0.2,0.3,0.4,0.5],
col2=[10,20,30,40,50],
coord1=[6,7,8,9,10],
coord2=[6,7,8,9,10]))
subset=big_grid
list_elem=["col1","col2"]
list_id=big_grid.id_col.values
dropm_elem=widgets.Dropdown(options=list(list_elem))
dropm_id=widgets.SelectMultiple(
options=list_id,
description="Active",
disabled=False
)
rangewidg=widgets.FloatRangeSlider(value=[big_grid[dropm_elem.value].min(),big_grid[dropm_elem.value].max()],
min=big_grid[dropm_elem.value].min(),
max=big_grid[dropm_elem.value].max(),
step=0.001,
readout_format='.3f',
description="Color Range",
continuous_update=False)
dropm_elem.observe(handle_elem_change,names='value')
dropm_id.observe(handle_id_change,names='value')
display(dropm_id)
widgets.interact(plot,elem=dropm_elem,rang=rangewidg)
所以,我想要第二个代码的行为,但在 widget.Hbox 中,可能不使用全局变量
【问题讨论】:
-
作为全局变量的替代方案,您可以使用某种类型的可变引用。就像字典或由类组成的对象。我个人喜欢使用带有 getter 和 setter 的类。
标签: python pandas plotly interactive ipywidgets