py2rpy转换报错:未定义ipywidgets.Text类型转换方案求助
py2rpy转换ipywidgets.Text对象失败问题排查
错误概述
运行Python中调用R的单元格魔法时,触发如下错误:
NotImplementedError: Conversion 'py2rpy' not defined for objects of type '<class 'ipywidgets.widgets.widget_string.Text'>'
相关代码
调用R魔法的Python代码及内嵌的R逻辑:
get_ipython().run_cell_magic('R', '-i cutoff -i mtry -i ntree -i data -o max_f1 -o max_cut -o max_mtry -o max_ntree -o max_precision -o max_recall', ''' library(randomForest) from types import NoneType NoneType = type(None) #9-24-2022 SL #from rpy2.robjects.conversion import localconverter as lc #with lc(ro.default_converter + pr.converter): # fileName_c = ro.conversion.py2rpy(fileName) # url_c = ro.conversion.py2rpy(url) #ro.globalenv['fileName'] = fileName_c #ro.globalenv['url'] = url_c #from rpy2.robjects import pandas2ri #pandas2ri.activate() #end 9-24-2022 SL data$target = factor(data$target) cutoff_list = unlist(strsplit("0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9",",")) #cutoff 9-24-2022 SL mtry_list = unlist(strsplit("2,3,4,5",",")) #mtry 9-24-2022 SL ntree_list = unlist(strsplit("100,500,1000",",")) #ntree 9-24-2022 SL set.seed(830) max_f1 = 0 max_cut = 0 max_mtry = 0 max_ntree = 0 max_precision = 0 max_recall = 0 # a nested for loop for ntree, mtry, cutoff? for (cut in cutoff_list ) { for (Mtry in mtry_list) { for (Ntree in ntree_list) { cut = as.numeric(cut) #9-24-2022 SL cut - should be "cutoff"? Mtry = as.numeric(mtry) #9-24-2022 SL mtry Ntree = as.numeric(NTree) #9-24-2022 SL Ntree fit_data <- randomForest(data$target ~ ., data=data, importance=TRUE, proximity=TRUE, cutoff=c(cut, 1-cut), ntree=Ntree, mtry=Mtry) true_positives = fit_data$confusion['1','1'] true_negatives = fit_data$confusion['0','0'] false_positives = fit_data$confusion['0','1'] false_negatives = fit_data$confusion['1','0'] accuracy = (true_positives + true_negatives)/nrow(data) precision = true_positives/(true_positives+false_positives) recall = true_positives/(true_positives + false_negatives) f1_score = 2*((recall*precision)/(precision+recall)) if (! is.nan(f1_score) && f1_score > max_f1) { max_f1 = f1_score max_cut = cut max_mtry = Mtry max_ntree = Ntree max_precision = precision max_recall = recall } } } } ''')
错误堆栈
NotImplementedError Traceback (most recent call last) Input In [122], in <cell line: 1>() ----> 1 get_ipython().run_cell_magic('R', '-i cutoff -i mtry -i ntree -i data -o max_f1 -o max_cut -o max_mtry -o max_ntree -o max_precision -o max_recall', 'library(randomForest)\n\nfrom types import NoneType\nNoneType = type(None)\n\n#from IPython.core.interactiveshell import InteractiveShell\n#InteractiveShell.ast_node_interactivity = "all"\n\n#9-24-2022 SL\n#from rpy2.robjects.conversion import localconverter as lc\n\n#with lc(ro.default_converter + pr.converter):\n# fileName_c = ro.conversion.py2rpy(fileName)\n# url_c = ro.conversion.py2rpy(url)\n#ro.globalenv['fileName'] = fileName_c\n#ro.globalenv['url'] = url_c\n\n#from rpy2.robjects import pandas2ri\n\n\n#pandas2ri.activate()\n#end 9-24-2022 SL\n\ndata$target = factor(data$target)\ncutoff_list = unlist(strsplit("0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9",",")) #cutoff 9-24-2022 SL\nmtry_list = unlist(strsplit("2,3,4,5",",")) #mtry 9-24-2022 SL\nntree_list = unlist(strsplit("100,500,1000",",")) #ntree 9-24-2022 SL\nset.seed(830)\nmax_f1 = 0\nmax_cut = 0\nmax_mtry = 0\nmax_ntree = 0\nmax_precision = 0\nmax_recall = 0\n# a nested for loop for ntree, mtry, cutoff?\nfor (cut in cutoff_list )\n{\n for (Mtry in mtry_list)\n {\n for (Ntree in ntree_list)\n {\n cut = as.numeric(cut) #9-24-2022 SL cut - should be "cutoff"?\n Mtry = as.numeric(mtry) #9-24-2022 SL mtry\n Ntree = as.numeric(NTree) #9-24-2022 SL Ntree\n fit_data <- randomForest(data$target ~ ., data=data, importance=TRUE, proximity=TRUE, cutoff=c(cut, 1-cut), ntree=Ntree, mtry=Mtry)\n true_positives = fit_data$confusion['1','1']\n true_negatives = fit_data$confusion['0','0']\n false_positives = fit_data$confusion['0','1']\n false_negatives = fit_data$confusion['1','0']\n accuracy = (true_positives + true_negatives)/nrow(data)\n precision = true_positives/(true_positives+false_positives)\n recall = true_positives/(true_positives + false_negatives)\n f1_score = 2*((recall*precision)/(precision+recall))\n if (! is.nan(f1_score) && f1_score > max_f1)\n {\n max_f1 = f1_score\n max_cut = cut\n max_mtry = Mtry\n max_ntree = Ntree\n max_precision = precision\n max_recall = recall\n }\n }\n }\n}\n\n') File ~\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2347, in InteractiveShell.run_cell_magic(self, magic_name, line, cell) 2345 with self.builtin_trap: 2346 args = (magic_arg_s, cell) -> 2347 result = fn(*args, **kwargs) 2348 return result File ~\anaconda3\lib\site-packages\rpy2\ipython\rmagic.py:755, in RMagics.R(self, line, cell, local_ns) 753 raise NameError("name '%s' is not defined" % input) 754 with localconverter(converter) as cv: -> 755 ro.r.assign(input, val) 757 if args.display: 758 try: File ~\anaconda3\lib\site-packages\rpy2\robjects\functions.py:203, in SignatureTranslatedFunction.__call__(self, *args, **kwargs) 201 v = kwargs.pop(k) 202 kwargs[r_k] = v -> 203 return (super(SignatureTranslatedFunction, self) 204 .__call__(*args, **kwargs)) File ~\anaconda3\lib\site-packages\rpy2\robjects\functions.py:118, in Function.__call__(self, *args, **kwargs) 116 def __call__(self, *args, **kwargs): 117 cv = conversion.get_conversion() -> 118 new_args = [cv.py2rpy(a) for a in args] 119 new_kwargs = {} 120 for k, v in kwargs.items(): 121 # TODO: shouldn't this be handled by the conversion itself ? File ~\anaconda3\lib\site-packages\rpy2\robjects\functions.py:118, in <listcomp>(.0) 116 def __call__(self, *args, **kwargs): 117 cv = conversion.get_conversion() -> 118 new_args = [cv.py2rpy(a) for a in args] 119 new_kwargs = {} 120 for k, v in kwargs.items(): 121 # TODO: shouldn't this be handled by the conversion itself ? File ~\anaconda3\lib\functools.py:888, in singledispatch.<locals>.wrapper(*args, **kw) 884 if not args: 885 raise TypeError(f'{funcname} requires at least ' 886 '1 positional argument') -> 888 return dispatch(args[0].__class__)(*args, **kw) File ~\anaconda3\lib\site-packages\rpy2\robjects\numpy2ri.py:134, in nonnumpy2rpy(obj) 129 return ro.default_converter.py2rpy(obj) 130 elif original_converter is None: 131 # This means that the conversion module was not "activated". 132 # For now, go with the default_converter. 133 # TODO: the conversion system needs an overhaul badly. -> 134 return ro.default_converter.py2rpy(obj) 135 else: 136 # The conversion module was "activated" 137 return original_converter.py2rpy(obj) File ~\anaconda3\lib\functools.py:888, in singledispatch.<locals>.wrapper(*args, **kw) 884 if not args: 885 raise TypeError(f'{funcname} requires at least ' 886 '1 positional argument') -> 888 return dispatch(args[0].__class__)(*args, **kw) File ~\anaconda3\lib\site-packages\rpy2\robjects\conversion.py:240, in _py2rpy(obj) 238 if isinstance(obj, _rinterface_capi.SupportsSEXP): 239 return obj -> 240 raise NotImplementedError( 241 "Conversion 'py2rpy' not defined for objects of type '%s'" % 242 str(type(obj)) 243 ) NotImplementedError: Conversion 'py2rpy' not defined for objects of type '<class 'ipywidgets.widgets.widget_string.Text'>'
原因分析
错误核心是:通过R魔法的-i参数传递给R环境的变量中,cutoff、mtry或ntree三者之一是ipywidgets的Text组件对象,而非实际的数值/字符串值。rpy2没有内置的转换规则,无法将UI组件直接转换为R可识别的对象。
另外,R代码中存在变量错误:
- 循环内
Mtry = as.numeric(mtry)应该改为Mtry = as.numeric(Mtry),因为mtry是外部传入的全局变量,循环迭代变量是Mtry Ntree = as.numeric(NTree)应该改为Ntree = as.numeric(Ntree),变量名大小写不匹配
解决方案
- 提取UI组件的实际值:如果
cutoff/mtry/ntree是ipywidgets的Text输入框,需要先获取其.value属性得到输入内容,再传递给R魔法。示例:# 假设cutoff是Text组件对象 cutoff_val = float(cutoff.value) mtry_val = int(mtry.value) ntree_val = int(ntree.value) # 传递提取后的值给R魔法 get_ipython().run_cell_magic('R', '-i cutoff_val -i mtry_val -i ntree_val -i data -o max_f1 ...', '...') - 修正R代码中的变量错误:将循环内的类型转换语句修正为:
cut = as.numeric(cut) Mtry = as.numeric(Mtry) Ntree = as.numeric(Ntree) - 可选:提前转换变量类型:从Text组件获取的value是字符串类型,提前转换为数值类型后再传递,避免R中转换可能出现的问题。
内容的提问来源于stack exchange,提问作者user19226726
相关产品推荐
相关产品推荐

