scipy.optimize на панде датафрейм - PullRequest
0 голосов
/ 16 октября 2018

Я пытался найти его, но с плохим результатом.

Может кто-нибудь объяснить мне, как выполнить optimize.minimize в Pandas DataFrame, чтобы минимизировать ошибку между категориями в 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, используя Solver

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

, поэтому конечный результат, который я пытаюсь найти:

средний абс 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 голосов
/ 16 октября 2018

Вам нужно определить функцию, которую можно запустить 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, как вы описали - перваяАргумент - это массив 1d с некоторым количеством значений (как требуется для оптимизации).Второй аргумент - это соответствующие строки для этих значений массива, а третий аргумент - ваш фрейм данных.Большая часть этого кода просто превращает ваши строки данных в значения, которые можно вычислить.

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

Я думаю, что ваше описание функции стоимости можетбыть немного не в себе, поэтому вам, возможно, придется настроить его.

...