在Jupyter Notebook中传参调用函数时触发IndexError问题求助
商品推荐系统数据传入对比模块报错问题
我正在开发一款商品推荐系统,在将数据传入对比模块时遇到困难。
数据情况
我的数据为电子表格格式,包含PN(产品编号)、Item(商品名称)、Description(描述)、Keywords(关键词)、Price(价格)字段,还有用于相似度计算的keywords_bin字段。
代码实现
from scipy import spatial def Similarity(Item1, Item2): a = products.iloc[Item1] b = products.iloc[Item2] keywordsA = a['keywords_bin'] keywordsB = b['keywords_bin'] kywdDistance = spatial.distance.cosine(keywordsA, keywordsB) return kywdDistance def get_recommendations(name): new_product = products[products['Item'].str.contains(name)].iloc[0].to_frame().T print('Selected Item: ',new_product.PN.values[0],' - ',new_product.Item.values[0],' - ', new_product.Description.values[0],' - ',new_product.Keywords.values[0],' - ', new_product.Price.values[0]) def getNeighbors(baseItem, K): distances = [] for index, row in products.iterrows(): if row['PN'] != baseItem['PN'].values[0]: dist = Similarity(baseItem['PN'].values[0], row['PN']) distances.append((row['PN'], dist)) distances.sort(key=operator.itemgetter(1)) neighbors = [] for x in range(K): neighbors.append(distances[x]) return neighbors K = 10 neighbors = getNeighbors(new_product, K) print('\nRecommended Products: \n') for neighbor in neighbors: print( products.iloc[neighbor[0]][0]+" | Keywords: "+ str(products.iloc[neighbor[0]][1]).strip('[]').replace(' ','')) print('\n')
我设置了下拉列表供用户选择商品,本该基于关键词相似度生成推荐结果,却触发了以下错误:
Cell In[237], line 7 1 button = widgets.Button( 2 description='Get Recommendations', 3 disabled=False, 4 button_style='', # 'success', 'info', 'warning', 'danger' or '' 5 tooltip='Get Recommendations') 6 display(button) ----> 7 button.on_click(get_recommendations(name)) Cell In[235], line 23, in get_recommendations(name) 20 return neighbors 22 K = 10 ---> 23 neighbors = getNeighbors(new_product, K) 24 print('\nRecommended Products: \n') 25 for neighbor in neighbors: Cell In[235], line 12, in get_recommendations.<locals>.getNeighbors(baseItem, K) 10 print(row.PN, ' ', baseItem.PN) 11 if row['PN'] != baseItem['PN'].values[0]: ---> 12 dist = Similarity(baseItem['PN'].values[0], row['PN']) 13 distances.append((row['PN'], dist)) 15 distances.sort(key=operator.itemgetter(1)) Cell In[26], line 4, in Similarity(Item1, Item2) 2 def Similarity(Item1, Item2): 3 a = products.iloc[Item1] ---> 4 b = products.iloc[Item2] 6 keywordsA = a['keywords_bin'] 7 keywordsB = b['keywords_bin'] File c:\program files\python38\lib\site-packages\pandas\core\indexing.py:1103, in _LocationIndexer.__getitem__(self, key) 1100 axis = self.axis or 0 1102 maybe_callable = com.apply_if_callable(key, self.obj) -> 1103 return self._getitem_axis(maybe_callable, axis=axis) File c:\program files\python38\lib\site-packages\pandas\core\indexing.py:1656, in _iLocIndexer._getitem_axis(self, key, axis) 1653 raise TypeError("Cannot index by location index with a non-integer key") 1655 # validate the location -> 1656 self._validate_integer(key, axis) 1658 return self.obj._ixs(key, axis=axis) File c:\program files\python38\lib\site-packages\pandas\core\indexing.py:1589, in _iLocIndexer._validate_integer(self, key, axis) 1587 len_axis = len(self.obj._get_axis(axis)) 1588 if key >= len_axis or key < -len_axis: -> 1589 raise IndexError("single positional indexer is out-of-bounds") IndexError: single positional indexer is out-of-bounds
错误原因及修复方案
核心问题
- 索引类型不匹配:
Similarity函数用iloc[]获取行,但传入的是产品编号PN(非整数),而iloc[]仅接受整数位置索引,直接导致越界错误。 - 按钮回调绑定错误:
button.on_click(get_recommendations(name))会直接执行函数,而非传入回调引用,导致逻辑触发时机错误。
分步修复
1. 修正按钮回调绑定
把直接执行函数改为传递回调引用,用lambda包装参数:
button.on_click(lambda _: get_recommendations(name))
2. 重构相似度计算逻辑
两种可选方案:
方案一:直接传递行数据
修改Similarity函数,直接接收行对象而非索引:def Similarity(rowA, rowB): return spatial.distance.cosine(rowA['keywords_bin'], rowB['keywords_bin'])然后在
getNeighbors中调用时传递行对象:dist = Similarity(baseItem.iloc[0], row)方案二:通过PN获取整数索引
如果要保留索引传递逻辑,先把PN转为对应的整数索引:# 在getNeighbors中获取基准商品的整数索引 base_idx = baseItem.index[0] # 遍历传递整数索引 dist = Similarity(base_idx, index)
3. 修正推荐结果输出
原代码用PN作为iloc[]的索引,改为通过PN查找行数据:
for neighbor in neighbors: product_row = products[products['PN'] == neighbor[0]].iloc[0] print(f"{product_row['PN']} | Keywords: {str(product_row['keywords_bin']).strip('[]').replace(' ','')}")
4. 优化选中商品的获取逻辑
无需转置为单行DataFrame,直接用Series更简洁:
new_product = products[products['Item'].str.contains(name)].iloc[0]
完整修复后代码示例
from scipy import spatial import operator import ipywidgets as widgets from IPython.display import display def Similarity(rowA, rowB): return spatial.distance.cosine(rowA['keywords_bin'], rowB['keywords_bin']) def get_recommendations(name): # 捕获商品不存在的情况 try: new_product = products[products['Item'].str.contains(name)].iloc[0] except IndexError: print(f"未找到包含名称 '{name}' 的商品") return print(f"Selected Item: {new_product['PN']} - {new_product['Item']} - {new_product['Description']} - {new_product['Keywords']} - {new_product['Price']}") def getNeighbors(baseItem, K): distances = [] for index, row in products.iterrows(): if row['PN'] != baseItem['PN']: dist = Similarity(baseItem, row) distances.append((row['PN'], dist)) # 余弦距离越小相似度越高,升序排序 distances.sort(key=operator.itemgetter(1)) return distances[:K] K = 10 neighbors = getNeighbors(new_product, K) print('\nRecommended Products: \n') for pn, dist in neighbors: product = products[products['PN'] == pn].iloc[0] print(f"{product['PN']} | Keywords: {str(product['keywords_bin']).strip('[]').replace(' ','')} | Similarity Distance: {dist:.4f}") print('\n') # 按钮初始化与绑定 button = widgets.Button( description='Get Recommendations', disabled=False, button_style='', tooltip='Get Recommendations' ) display(button) # 替换"下拉框变量名"为实际的下拉框控件名称 button.on_click(lambda _: get_recommendations(下拉框变量名.value))
内容的提问来源于stack exchange,提问作者ChelleyG
相关产品推荐
相关产品推荐

