如何将Pandas含lambda的apply函数转换为Ruby(pandas.rb)
Pandas Python代码转Ruby(基于pandas.rb和numpy.rb)
基础语法直接转换示例
对于Pandas中简单的指数加权平均、滑动窗口标准差这类操作,可以直接对应到Ruby的pandas.rb,语法几乎一致:
Python 代码
# DF 是Pandas的DataFrame对象 DF['VAL'].ewm(span = vDAY).mean() DF['VOLAT'].rolling(vDAY).std()
Ruby 对应代码
# df 是pandas.rb的DataFrame对象 df['VAL'].ewm(span: vDAY).mean df['VOLAT'].rolling(vDAY).std
带函数参数的apply方法转换问题
当遇到Pandas中需要传入自定义函数的apply方法时,转换会遇到障碍。以下是对应的Python原代码:
import numpy as np # 对滑动窗口内的数据执行线性拟合,返回拟合直线的斜率 DF['VAL'].rolling(vDAY).apply(lambda x: np.polyfit(range(len(x)), x, 1)[0]) # 输出结果为NaN或浮点数值
尝试的错误写法及报错
最初尝试用Ruby的lambda模拟Python的lambda,但多种写法均触发错误:
# 定义lambda,单独调用时输出符合预期 polyfit = ->(x) { t = Numpy.polyfit((0...x.size).to_a, x, 1); t[0] } puts polyfit.call(<传入数组参数>) # 单独调用时输出正常 # 错误写法1:通过&传递lambda df['VAL'].rolling(vDAY).apply(&polyfit) # 报错信息:`apply': <class 'TypeError'>: must be real number, not NoneType (PyCall::PyError) # 错误写法2:在块内调用lambda df['VAL'].rolling(vDAY).apply{ |x| polyfit.call(x) } # 报错信息:`apply': <class 'TypeError'>: apply() missing 1 required positional argument: 'func' (PyCall::PyError) # 错误写法3:直接传入lambda对象 df['VAL'].rolling(vDAY).apply(polyfit) # 报错信息:`apply': <class 'TypeError'>: must be real number, not NoneType (PyCall::PyError) # 错误写法4:传入方法名符号 df['VAL'].rolling(vDAY).apply(:polyfit) # 报错信息:`apply': <class 'TypeError'>: 'str' object is not callable (PyCall::PyError)
正确解决方案:使用Ruby Proc对象
问题根源在于pandas.rb的apply方法需要接收符合Python可调用对象规范的Ruby对象,此时应该使用Ruby的Proc而非lambda。正确代码如下:
polyfit = Proc.new { |x| t = Numpy.polyfit((0...x.size).to_a, x, 1); t[0] } df['VAL'].rolling(vDAY).apply(polyfit)
内容的提问来源于stack exchange,提问作者Sovalina
相关产品推荐
相关产品推荐

