1

でリストを引数として渡したいoptimize.newton。1 つの csv をインポートし、各行を配列に格納しました。このコードは次のようになります。

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

今、私が見るとarray[1]、次のようになります。'2,6,76,45,78,1\r\n'

1 つの関数を次のように定義しました。

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言葉を与えています": can only concatenate tuple (not "str") to tuple"

誰かがここで私を助けることができますか? タプル要素はコンマで区切らなければならないことを知っていて、私も書いてみましargs=(x,)たが、うまくいきませんでした。

4

2 に答える 2

1

まず、あなたのコードでarrayは、実際には numpy 配列ではないことに注意してください。これは通常の Pythonlistの文字列です。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と、パラメーターは 6 つのパラメーター値のシーケンスargs=を取得する必要があります。各行に6 つの数値ではなく単一の文字列が含まれていたため、元のコードは機能していませんでした。* がnrows x 6 の配列になったので、各行には 6 つの数値が含まれるため、次のようにするだけです。arraydata

res = [optimize.newton(func, 5102, args=row) for row in data]

*クラスとの混乱arraydata避けるために、変数の名前を に変更したことに注意してくださいnp.array


アップデート

元のコードに、最初は気付かなかった別のエラーがありました。のドキュメントをご覧くださいscipy.optimize.newton

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

(あなたが呼び出した)への最初の引数はxパラメータに対応している必要があります。その後、 を使用して渡す必要がある追加の引数は(定義に従って)5つだけです。電話をかけようとするとfunc()ab ... fargs=

optimize.newton(func, 5102, args=(422, 858, 129, 312, 79, 371))

5102 がパラメータとして解釈さx0れ、最初の引数として に渡されますfunc()。タプルの6 つの値はargs=追加の引数として扱われるため、関数は実際には合計7 つの引数を取得します。

func(5102, 422, 858, 129, 312, 79, 371)

明らかに、func()は 6 つの引数を取るように定義されているため、エラーが発生します。これを修正する正しい方法は、関数のパラメーターをどのように解釈するかによって異なります。の目標は、f(x, a, b, c, ...) = 0 となるxnewtonの値を見つけることです。

6 つのパラメータのうちどれを最小化したいfunc()ですか?


完全な説明

args=data[0]もう少し興味深い質問は、追加の引数をタプルではなく配列 (例: ) として渡すと、なぜエラーが発生しないのかということです。答えはもう少し複雑ですが、興味がある場合は読み進めてください。

ソースコードをscipy.optimize.newton見ると、関数が初めて呼び出される行を見つけることができます:

q0 = func(*((p0,) + args))

この場合、 p0andは へp1x0引数となりnewton()、 andargsは追加の引数のセットです。

q0 = func(*((5102,) + (422, 858, 129, 312, 79, 371)))

(p0,)がタプルで、argsもタプルである場合、+演算子はこれら 2 つのタプルを結合します。

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]))

の各要素に値+追加します。p0args

q0 = func(*(5524, 5960, 5231, 5414, 5181, 5473))

6 つの引数しかないのでfunc()、呼び出しは成功しますがnewton、間違った答えに収束します!

これはscipyでは特に良い設計ではないと思います.他のほとんどの場合、リスト、タプル、配列などを含む配列のような入力でうまくいくので、私を捕まえました.公平を期すために、newtonそれargs=はタプルですが、安全のために型チェックを行うか、明示的にタプルにキャストします。私はscipyでこの問題を修正しようとするかもしれません。

于 2015-01-23T11:22:58.957 に答える
0

まず、その末尾を削除する必要があり、'\r', '\t'そのために使用できます.strip()。これで、目的の要素がコンマで区切られた文字列ができました。ここで.split()メソッドを使用して、指定された文字列で分割する文字を渡すことができます。最後に、最初のパラメーター (この場合は int ) として関数を受け取る map() 関数を使用し、2 番目の引数はリストまたはタプルであり、タプルのリストの各要素を最初のパラメーターとして渡された関数にマップします。

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(',')))
于 2015-01-22T14:41:38.647 に答える