Python:在scipy.optimize.newton中将列表作为参数传递

Python:在scipy.optimize.newton中将列表作为参数传递,python,python-2.7,numpy,scipy,pythonxy,Python,Python 2.7,Numpy,Scipy,Pythonxy,我想在optimize.newton中将列表作为参数传递。 我已经导入了一个csv,并将每一行存储在一个数组中。此操作的代码如下所示: with open('rand1.csv','rb') as f: array=[] for line in f: array.append(line) 现在,如果我看一下数组[1],它看起来像:'2,6,76,45,78,1\r\n' 我将一个函数定义为: def func(a,b,c,d,e,f): return a

我想在
optimize.newton
中将列表作为参数传递。 我已经导入了一个csv,并将每一行存储在一个数组中。此操作的代码如下所示:

with open('rand1.csv','rb') as f:
    array=[]
    for line in f:
        array.append(line)
现在,如果我看一下
数组[1]
,它看起来像:
'2,6,76,45,78,1\r\n'

我将一个函数定义为:

def func(a,b,c,d,e,f):
    return a*b*c-d*e-f
我运行的牛顿法如下:

res=[optimize.newton(func,5102,args=(x)) for x in array[0]]
但是它给了我一个
TypeError
“:只能将tuple(而不是“str”)连接到tuple”


有人能帮我吗?我知道元组元素必须用逗号分隔,我也尝试过编写
args=(x,)
,但它不起作用。

首先你需要删除尾随的
'\r','\t'
,为此你可以使用
.strip()
,现在你有了一个字符串,其中所需的元素用逗号分隔,在这里,您可以使用
.split()
方法,将要拆分的字符传递给给定的字符串。最后,我们使用map()函数,该函数将一个函数作为第一个参数(在本例中为int),第二个参数是一个列表或元组,并将该元组列表的每个元素与作为第一个参数传递的函数进行映射

line = '2,6,76,45,78,1\r\n'
line_stripped = line.strip()
print line_stripped
>>> '2,6,76,45,78,1'

line_splitted = line_stripped.split(",")
print line_splitted
>>> '2' ,'6', '76', '45', '78', '1'

line_integers = map(int,line_splitted)
print line_integers
>>> [2, 6, 76, 45, 78, 1]
结合以上所有步骤,我们可以清楚地将其写成:

with open('rand1.csv','rb') as f:
    array=[]
    for line in f:
        array.append(map(int,line.strip().split(',')))

首先,请记住,在代码中,
array
实际上不是一个numpy数组-它是一个普通的Python
字符串列表。可以通过拆分字符串并将元素转换为整数来处理此列表,如Anmol_uppal的回答,但将csv文件的内容直接转换为nrows x 6 numpy数组要简单得多,例如使用
np.loadtxt

import numpy as np

data = np.loadtxt('rand1.csv', delimiter=',', dtype=np.int)
print(repr(data[0]))
# array([ 2,  6, 76, 45, 78,  1])
现在,当您调用
optimize.newton
时,
args=
参数应该得到6个参数值的序列。原始代码不起作用,因为
数组中的每一行都包含一个字符串,而不是6个数值。既然
data
*是一个nrows x 6数组,那么每行将包含6个数值,因此您现在只需执行以下操作:

res = [optimize.newton(func, 5102, args=row) for row in data]
*请注意,我已将变量
array
重命名为
data
,以避免与
np.array
类混淆


更新 您的原始代码中还有一个错误,我最初没有发现。请参阅以下文档:

func:函数

需要其零的函数。它必须是形式为f(x,a,b,c…)的单个变量的函数,其中a,b,c。。。是可以在args参数中传递的额外参数

x0:浮动

零点的初始估计值,应该在实际零点附近

现在看看您的函数定义:

def func(a,b,c,d,e,f):
    return a*b*c-d*e-f
func()
(您称之为
a
)的第一个参数应该对应于x参数,然后只有5个额外的参数(
b…f
,根据您的定义)需要使用
args=
传递。当你试着打电话的时候

optimize.newton(func, 5102, args=(422, 858, 129, 312, 79, 371))
发生的情况是,5102被解释为
x0
参数,并作为第一个参数传递给
func()
args=
元组中的6个值被视为额外参数,因此您的函数实际上总共获得7个参数:

func(5102, 422, 858, 129, 312, 79, 371)
显然,
func()
被定义为接受6个参数,因此您会得到一个错误。解决此问题的正确方法取决于如何解释函数的参数。牛顿的目标是找到一个x的值,使得f(x,a,b,c,…)=0

您希望将6个参数中的哪一个最小化
func()
over


充分解释 一个稍微有趣的问题是,当您将额外的参数作为数组(例如,
args=data[0]
)而不是元组传递时,为什么不会出现错误。答案有点复杂,但如果你感兴趣,请继续阅读

如果查看一下,您可以找到第一次调用函数的行:

q0 = func(*((p0,) + args))
在这种情况下,
p0
p1
将是
x0
newton()
的参数,
args
是一组额外的参数:

q0 = func(*((5102,) + (422, 858, 129, 312, 79, 371)))
(p0,)
是一个元组,如果
args
也是一个元组,那么
+
操作符将把这两个元组连接在一起:

q0 = func(*(5102, 422, 858, 129, 312, 79, 371))
最后,
*
解压元组,将参数传递给
func
。最后一次呼叫如下所示:

q0 = func(5102, 422, 858, 129, 312, 79, 371)
这将引发错误,因为一个6参数函数有7个参数。但是,当
args
np.array
时:

q0 = func(*(5102,) +  array([422, 858, 129, 312, 79, 371]))
+
将向
args
中的每个元素添加值
p0

q0 = func(*(5524, 5960, 5231, 5414, 5181, 5473))
由于现在只有6个参数指向
func()
调用将成功,但
newton
将收敛到错误的答案


我认为这在scipy中不是特别好的设计-它让我很吃惊,因为在大多数其他情况下,任何类似数组的输入都可以,包括列表、元组、数组等。公平地说,
newton
的文档中确实说
args=
应该是元组,但为了安全起见,我仍然会进行类型检查或将其显式转换为元组。我可能会尝试在scipy中修复此问题。

首先
strip()
行(在追加之前)并使用
.split(',')
方法这有助于我摆脱“\r',“\t”,但我仍然无法运行optimize.newton函数。这里有什么建议吗?谢谢,这稍微解决了我的问题。但我在这里没有更多的疑问。如果我在一个有8行6列的csv上运行您的代码,它就可以正常工作。如果我是正确的,形成的阵列将是8x6。“res”变量将有8个值。但如果我只想为第一行运行优化代码呢?我无法为数据[0]中的行运行以下命令:res=[optimize.newton(func,5102,args=row)。此外,如果我通过手动指定值来运行代码,则会为