我已经写了下面的函数来做两个参数的线性回归(它背后的实际数学与这个问题无关)。它有两个函数,f1
,f2
,和两个列表xs
,ys
:
def lr2par(f1, f2, xs, ys):
c11 = sum(map(lambda x: (f1(x))**2, xs))
c12 = sum(map(lambda x: f1(x) * f2(x), xs))
c22 = sum(map(lambda x: (f2(x))**2, xs))
d1 = sum(map(lambda x, y: y*f1(x), xs,ys))
d2 = sum(map(lambda x, y: y*f2(x), xs,ys))
a1 = -(c22*d1 - c12*d2)/(c12*c12 - c11*c22)
a2 = (c12*d1 - c11*d2)/(c12*c12 - c11*c22)
return (c11, c12, c22, d1, d2, a1, a2)
只要xs
和ys
是列表,它就可以正常工作。但是,正如您所看到的,它是以一种非常函数化的风格编写的,所以我当然希望能够在函数代码中优雅地使用这个函数。这包括在我将一个函数输入到函数之前,在一个列表上调用一个函数,如map
,如本例中的ys
参数:
lr2par(lambda x: x, lambda x: 1, [1, 3, 5, 7], map(math.log, [130, 150, 175, 210]))
对我来说,这看起来很自然,我希望它能工作(尽管我是一个python noob)。事实证明不是。我很确定问题是ys
参数现在不再是一个列表,而是一个迭代器(在python中使用函数工具时,它似乎是主要类型),只能迭代一次,所以当它涉及到行时
d2 = sum(map(lambda x, y: y*f2(x), xs,ys))
ys
只是空的。我想用惯用的功能性python方法来解决这个问题。我目前的解决方案是添加行
xs = list(xs)
ys = list(ys)
到函数体的开头。这是可行的,但这是解决问题的好方法吗?我是否必须将这些行添加到几乎所有使用对象集合的函数中,并希望这些函数能够很好地与map
、filter
和zip
等函数配合使用?你知道吗
一般来说,不能对iterable进行两次迭代。如果需要,必须首先将其转换为序列,就像对
list
所做的那样,这实际上是一个非常标准的解决方案。你知道吗主要的问题是它可能效率低下,因为它会复制任何传入的列表或元组,因此您可能需要检查这些列表或元组,并用以下helper函数替换
list
:(作为站点注释,如果用生成器理解替换
map
和lambda
,代码的可读性会提高很多;如果重写为使用NumPy,代码的可读性也会提高很多,我建议在Python中使用NumPy)相关问题 更多 >
编程相关推荐