在 pandas 数据帧上使用 scipy NonlinearConstraint 求解非线性方程
Solve non linear equations with scipy NonlinearConstraint over pandas dataframe
我正在尝试求解方程组:
其中 a、b 和 c 是来自 pandas 数据框的列。我曾经使用 Excel,其中我 运行 一个宏
通过更改其他列(函数)的值在一列(残差)中搜索,但我不知道如何在 Python 中执行此操作,我已经问过 here,但没有还没回答。
我试过fsolve,但结果总是我最初的猜测,所以,我猜它需要一些边界,但fsolve不允许引入边界,这就是我尝试的原因scipyn.NonlinearConstraint
以下是要解决的数据集和函数:
import numpy as np
import pandas as pd
import scipy.optimize as opt
from scipy.optimize import NonlinearConstraint
a = np.linspace(300,400,30)
b = np.random.randint(700,18000,30)
c = np.random.uniform(1.4,4.0,30)
df = pd.DataFrame({'A':a, 'B':b, 'C':c})
def func(zGuess,*Params):
x,y,z = zGuess
a,b,c = Params
eq_1 = (((3.47-np.log10(y))**2+(np.log10(c)+1.22)**2)**0.5) - x
eq_2 = ((a/101.32) * (101.32/b)** z) - y
eq_3 = (0.381 * x + 0.05 * (b/101.32) -0.15) - z
return eq_1,eq_2,eq_3
zGuess = np.array([2.6,20.2,0.92])
up_bound = (9,np.inf,1.1)
low_bound = (0,-np.inf,0)
这里我尝试用 fsolve 来解决:
df['x'],df['y'],df['z'] = zip(*df.apply(lambda x: opt.fsolve(func,zGuess,args=(x['A'],x['B'],x['C'])),1) )
此处使用非线性约束:
df['x'],df['y'],df['z'] = zip(*df.apply(lambda x: NonlinearConstraint(func(zGuess,x['A'],x['B'],x['C']),low_bound,up_bound),1) )
但是对于非线性约束,它给出了一个错误:
TypeError: zip argument #1 must support iteration
我什至试图最小化 pandas 数据帧:
def func2(zGuess,*Params):
x,y = zGuess
a,b,c,n = Params
eq_1 = (((3.47-np.log10(y))**2+(np.log10(c)+1.22)**2)**0.5) - x
eq_2 = ((a/101.32) * (101.32/b)** n) - y
return eq_1,eq_2,eq_3
zGuess2 = np.array([2.6,20.2])
n = np.linspace(0,1.,500)
for i in n:
df['x'],df['y'] = zip(*df.apply(lambda x: opt.fsolve(func2,zGuess2,args=(x['a'],x['b'],x['c'],i)),1))
df['n_calc'] = df.apply(lambda x: (0.381 * x['x'] + 0.05 * (x['b']/101.32) - 0.15),1)
res = np.abs(df['n_calc'] - i)
if res <= 1e-5:
n_solver = i
df['n_solver'].append(n_solver)
我从没想过 excel 中的 go seak 这样简单的事情会在 python 中执行起来如此困难,我真的需要一些帮助。
我会忽略你问题的 pandas 部分,只会解决优化部分。忽略所有 pandas 噪声,您的问题基本上是如何求解具有简单变量边界的方程。这已被多次回答,例如参见here。
这里有一些提示:
你的边界没有意义,例如对数仅定义为正值,不定义为零。
请熟悉np.ndarrays。使用 scipy.optimize.
会让您的生活更轻松
您的 NonlinearConstraint 也没有意义。这是一个可以传递给 scipy.optimize.minimize
的对象。它不可调用或优化方法。
如果你想求解变量有界的方程,你需要将问题重新表述为非线性优化问题并通过scipy.optimize.minimize
求解,见上面链接回答更多细节。请注意,我更改了您的 func
,使其 returns 成为 np.ndarray。
以下是一个工作版本,可以解决数据框中每一行的方程式。随意重写它,以便您可以在 df.apply()
.
中使用它
from scipy.optimize import minimize
def func(zz, *params):
x,y,z = zz
a,b,c = params
eq_1 = (((3.47-np.log10(y))**2+(np.log10(c)+1.22)**2)**0.5) - x
eq_2 = ((a/101.32) * (101.32/b)** z) - y
eq_3 = (0.381 * x + 0.05 * (b/101.32) -0.15) - z
return np.array((eq_1,eq_2,eq_3))
bounds = [(1e-6, None), (1e-6, None), (1e-6, None)]
zGuess = np.array([2.6,20.2,0.92])
# create the new columns
df[["x", "y", "z"]] = np.zeros((30, 3))
for i, row in df.iterrows():
params = row.values[:3]
res = minimize(lambda x: np.sum(func(x, *params)**2), zGuess, bounds=bounds)
# res.x contains your solution
# let's write the values into the dataframe
for k, val in zip(['x', 'y', 'z'], res.x):
df.loc[i, k] = val
I never thought something so simple like go seak in excel would give such difficulty to perform in python
在不阅读文档的情况下混合几个不同的概念,使得在任何任意编程语言中的每项任务都变得困难。
我正在尝试求解方程组:
其中 a、b 和 c 是来自 pandas 数据框的列。我曾经使用 Excel,其中我 运行 一个宏 通过更改其他列(函数)的值在一列(残差)中搜索,但我不知道如何在 Python 中执行此操作,我已经问过 here,但没有还没回答。
我试过fsolve,但结果总是我最初的猜测,所以,我猜它需要一些边界,但fsolve不允许引入边界,这就是我尝试的原因scipyn.NonlinearConstraint 以下是要解决的数据集和函数:
import numpy as np
import pandas as pd
import scipy.optimize as opt
from scipy.optimize import NonlinearConstraint
a = np.linspace(300,400,30)
b = np.random.randint(700,18000,30)
c = np.random.uniform(1.4,4.0,30)
df = pd.DataFrame({'A':a, 'B':b, 'C':c})
def func(zGuess,*Params):
x,y,z = zGuess
a,b,c = Params
eq_1 = (((3.47-np.log10(y))**2+(np.log10(c)+1.22)**2)**0.5) - x
eq_2 = ((a/101.32) * (101.32/b)** z) - y
eq_3 = (0.381 * x + 0.05 * (b/101.32) -0.15) - z
return eq_1,eq_2,eq_3
zGuess = np.array([2.6,20.2,0.92])
up_bound = (9,np.inf,1.1)
low_bound = (0,-np.inf,0)
这里我尝试用 fsolve 来解决:
df['x'],df['y'],df['z'] = zip(*df.apply(lambda x: opt.fsolve(func,zGuess,args=(x['A'],x['B'],x['C'])),1) )
此处使用非线性约束:
df['x'],df['y'],df['z'] = zip(*df.apply(lambda x: NonlinearConstraint(func(zGuess,x['A'],x['B'],x['C']),low_bound,up_bound),1) )
但是对于非线性约束,它给出了一个错误:
TypeError: zip argument #1 must support iteration
我什至试图最小化 pandas 数据帧:
def func2(zGuess,*Params):
x,y = zGuess
a,b,c,n = Params
eq_1 = (((3.47-np.log10(y))**2+(np.log10(c)+1.22)**2)**0.5) - x
eq_2 = ((a/101.32) * (101.32/b)** n) - y
return eq_1,eq_2,eq_3
zGuess2 = np.array([2.6,20.2])
n = np.linspace(0,1.,500)
for i in n:
df['x'],df['y'] = zip(*df.apply(lambda x: opt.fsolve(func2,zGuess2,args=(x['a'],x['b'],x['c'],i)),1))
df['n_calc'] = df.apply(lambda x: (0.381 * x['x'] + 0.05 * (x['b']/101.32) - 0.15),1)
res = np.abs(df['n_calc'] - i)
if res <= 1e-5:
n_solver = i
df['n_solver'].append(n_solver)
我从没想过 excel 中的 go seak 这样简单的事情会在 python 中执行起来如此困难,我真的需要一些帮助。
我会忽略你问题的 pandas 部分,只会解决优化部分。忽略所有 pandas 噪声,您的问题基本上是如何求解具有简单变量边界的方程。这已被多次回答,例如参见here。
这里有一些提示:
你的边界没有意义,例如对数仅定义为正值,不定义为零。
请熟悉np.ndarrays。使用 scipy.optimize.
会让您的生活更轻松您的 NonlinearConstraint 也没有意义。这是一个可以传递给
scipy.optimize.minimize
的对象。它不可调用或优化方法。如果你想求解变量有界的方程,你需要将问题重新表述为非线性优化问题并通过
scipy.optimize.minimize
求解,见上面链接回答更多细节。请注意,我更改了您的func
,使其 returns 成为 np.ndarray。
以下是一个工作版本,可以解决数据框中每一行的方程式。随意重写它,以便您可以在 df.apply()
.
from scipy.optimize import minimize
def func(zz, *params):
x,y,z = zz
a,b,c = params
eq_1 = (((3.47-np.log10(y))**2+(np.log10(c)+1.22)**2)**0.5) - x
eq_2 = ((a/101.32) * (101.32/b)** z) - y
eq_3 = (0.381 * x + 0.05 * (b/101.32) -0.15) - z
return np.array((eq_1,eq_2,eq_3))
bounds = [(1e-6, None), (1e-6, None), (1e-6, None)]
zGuess = np.array([2.6,20.2,0.92])
# create the new columns
df[["x", "y", "z"]] = np.zeros((30, 3))
for i, row in df.iterrows():
params = row.values[:3]
res = minimize(lambda x: np.sum(func(x, *params)**2), zGuess, bounds=bounds)
# res.x contains your solution
# let's write the values into the dataframe
for k, val in zip(['x', 'y', 'z'], res.x):
df.loc[i, k] = val
I never thought something so simple like go seak in excel would give such difficulty to perform in python
在不阅读文档的情况下混合几个不同的概念,使得在任何任意编程语言中的每项任务都变得困难。