在熊猫数据框上进行scipy.optimize

时间:2018-10-16 14:41:58

标签: python pandas optimization scipy solver

我尝试搜索它,但结果不佳。

有人可以向我解释如何在Pandas DataFrame上执行optimize.minimize,从而使DataFrame中的类别与结果列之间的错误最小化

考虑以下示例:

import pandas as pd

df = pd.DataFrame({'prod': ['prod1', 'prod2', 'prod3', 'prod4', 'prod5', 'prod6'],
                   'cat': ['cat1', 'cat1', 'cat2', 'cat2', 'cat3', 'cat1'],
                   'dog': ['dog1', 'dog2', 'dog1', 'dog2', 'dog2', 'dog3'],
                   'result': [20, 10, 30, 50, 45, 120]})

对于每个cat1,cat2,cat3,dog1,dog2和dog3,我都想找到使该等式最小的值:

import numpy as np

np.average(np.abs(df['result'] - ('min for values in cat column * min for values in dog column'))) / np.average(df['result'])

我能够使用求解器在Excel中复制

prod    cat     dog result  cat*dog abs
prod1   cat1    dog1    20  17.38   2.61
prod2   cat1    dog2    10  27.34   17.35
prod3   cat2    dog1    30  26.91   3.09
prod4   cat2    dog2    50  42.32   7.67
prod5   cat3    dog2    45  45.00   0.00
prod6   cat1    dog3    120 20.64   99.36

所以我想要找到的最终分数是:

平均Abs为22 /平均结果为45.83 = 0.47

以下是规划求解为动物返回的值:

cat1    3.59194254
cat2    5.559980313
cat3    5.91078751
dog1    4.840109868
dog2    7.613201994
dog3    5.746396256

如何在Python中复制它?

1 个答案:

答案 0 :(得分:1)

您需要定义一个optimize.minimize可以运行的函数(以使其知道要最小化的内容)。

import pandas as pd
import numpy as np
from scipy import optimize

df = pd.DataFrame({'prod': ['prod1', 'prod2', 'prod3', 'prod4', 'prod5', 'prod6'],
                   'cat': ['cat1', 'cat1', 'cat2', 'cat2', 'cat3', 'cat1'],
                   'dog': ['dog1', 'dog2', 'dog1', 'dog2', 'dog2', 'dog3'],
                   'result': [20, 10, 30, 50, 45, 120]})

因此,让我们根据您的描述来定义animal_error函数-第一个参数是一维数组,具有一定数量的值(这是优化所要求的)。第二个参数是这些数组值的对应字符串,第三个参数是您的数据框。大部分代码只是将您的数据框字符串转换为可以计算的值。

def animal_error(val, animal, df):
    assert len(val) == len(animal)
    lookup = dict()
    for i in range(len(val)):
        lookup[animal[i]] = val[i]
    df = df.replace(lookup)
    error = np.abs(df['result'] - np.multiply(df['cat'], df['dog']))
    return np.mean(error) / np.mean(df['result'])

现在,您可以将字符串制成数组:

animals = np.concatenate([df['dog'].unique(), df['cat'].unique()])

为求解器设置一个合理的初始值:

initial = np.repeat(np.sqrt(df['result'].mean()), animals.size)

并运行最小化器:

res = optimize.minimize(animal_error, args=(animals, df), x0=initial, method = 'Nelder-Mead', options={'maxiter':10000})
res_df = pd.DataFrame({'animal': animals, 'min_val':res.x})

最终结果如下:

>>> res.fun
0.08676411624175694

  animal    min_val
0   dog1   3.754194
1   dog2   5.296533
2   dog3  22.526566
3   cat1   5.327044
4   cat2   9.307979
5   cat3   8.496109

我认为您的成本功能描述可能有点过时,因此您可能需要对其进行调整。