使用Jupyter Widget值切片Pandas DataFrame触发step必须≥0错误
问题描述
在Jupyter Notebook中使用Jupyter Widget与函数交互,通过下拉框切换不同图表,选项来自DataFrame。以下是可正常运行的伪代码:
def plot_option(x): plot(x) option = widgets.Dropdown( options=[ df[column].iloc[i] for i in range(10)]) interact(plot_option,x=option)
但实际实现中希望Dropdown的值为排序后DataFrame的索引i,修改代码后触发错误:
option = widgets.Dropdown( options=[i for i in range(10)]) interact(plot_option,x=df[column].iloc[option.value])
错误信息:
step must >= 0, not -2
疑问:option.value难道不是整数吗?为何不能在interact定义中进行切片操作?
回溯信息:
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[332], line 11 8 def plot_tiles_option(board,free_coords,coord): 9 plot_tiles(board,free_coords,local_tiles(coord,2),coord=coord) ---> 11 interact(plot_tiles_option,board=fixed(Board),free_coords=fixed(Free_coords),coord=top10['coordinates'].iloc[int(option.value)]) File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\ipywidgets\widgets\interaction.py:536, in _InteractFactory.__call__(self, _InteractFactory__interact_f, **kwargs) 528 return self 530 # positional arg support in: https://gist.github.com/8851331 531 # Handle the cases 1 and 2 532 # 1. interact(f, **kwargs) 533 # 2. @interact 534 # def f(*args, **kwargs): 535 # ... ---> 536 w = self.widget(f) 537 try: 538 f.widget = w File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\ipywidgets\widgets\interaction.py:452, in _InteractFactory.widget(self, f) 436 def widget(self, f): 437 """ 438 Return an interactive function widget for the given function. 439 (...) 450 The function to which the interactive widgets are tied. 451 """ ---> 452 return self.cls(f, self.opts, **self.kwargs) File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\ipywidgets\widgets\interaction.py:187, in interactive.__init__(self, _interactive__interact_f, _interactive__options, **kwargs) 185 getcallargs(f, **{n:v for n,v,_ in new_kwargs}) 186 # Now build the widgets from the abbreviations. ---> 187 self.kwargs_widgets = self.widgets_from_abbreviations(new_kwargs) 189 # This has to be done as an assignment, not using self.children.append, 190 # so that traitlets notices the update. We skip any objects (such as fixed) that 191 # are not DOMWidgets. 192 c = [w for w in self.kwargs_widgets if isinstance(w, DOMWidget)] File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\ipywidgets\widgets\interaction.py:286, in interactive.widgets_from_abbreviations(self, seq) 284 if isinstance(abbrev, Widget) and (not isinstance(abbrev, ValueWidget)): 285 raise TypeError("{!r} is not a ValueWidget".format(abbrev)) ---> 286 widget = self.widget_from_abbrev(abbrev, default) 287 if widget is None: 288 raise ValueError("{!r} cannot be transformed to a widget".format(abbrev)) File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\ipywidgets\widgets\interaction.py:302, in interactive.widget_from_abbrev(cls, abbrev, default) 299 return abbrev 301 if isinstance(abbrev, tuple): ---> 302 widget = cls.widget_from_tuple(abbrev) 303 if default is not empty: 304 try: File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\ipywidgets\widgets\interaction.py:382, in interactive.widget_from_tuple(o) 380 step = o[2] 381 if step <= 0: ---> 382 raise ValueError("step must be >= 0, not %r" % step) 383 min, max, value = _get_min_max_value(o[0], o[1], step=step) 384 if all(isinstance(_, Integral) for _ in o): ValueError: step must be >= 0, not -2
问题原因与解决方案
错误原因
你在interact里直接写x=df[column].iloc[option.value]时,interact会把这个值当成静态参数解析,而非绑定下拉框的动态值。如果df[column].iloc[option.value]返回的是类似元组的结构,interact会误将其识别为生成滑块组件的参数(比如(min, max, step)),当其中的step为负数时就会触发该错误。
另外,option.value本身是整数,但你在interact中直接计算出了最终值,这相当于给x传入一个固定值,而非绑定下拉框组件,完全失去了交互的意义。
正确写法
要实现通过下拉框选择索引、再用索引取DataFrame数据绘图的需求,应将下拉框组件传给interact,然后在绘图函数内部用传入的索引获取数据:
def plot_option(idx): # 在函数内部根据索引获取数据 x = df[column].iloc[idx] plot(x) # 下拉框选项为索引0-9 option = widgets.Dropdown(options=[i for i in range(10)]) # 直接把下拉框组件传给interact的x参数 interact(plot_option, x=option)
或者更简洁的写法,无需提前定义Dropdown,直接给interact传选项列表,它会自动生成下拉框:
def plot_option(idx): x = df[column].iloc[idx] plot(x) # 直接传入选项范围,interact自动生成下拉框 interact(plot_option, x=list(range(10)))
这样就能实现选择索引后动态绘图的效果,同时避免interact误解析参数的问题。
内容的提问来源于stack exchange,提问作者sybren osinga
相关产品推荐
相关产品推荐

