0

TYPO FIXEDD

I need to perform a minimization optimisation for each timestep in my timeseries. The optimisation sets the price based on values in different columns across the row and a series of inequality constraints.

My Dataframe has the following columns across time series of 48 years:

['CAPEX_TOT', 'CAPEX_R', 'CAPEX_WS', 'debt_BP', 'principal','interest',
   'debt_service', 'debt_EP', 'OPEX', 'OPEX_R', 'OPEX_WS',
   'DELIVERY_BAWSCA', 'DELIVERY_OTHER_DEMAND',
   'DELIVERY_SAN_FRANCISCO_CITY', 'DELIVERIES_WS', 'DELIVERIES_R',
   'PRICE_crR', 'PRICE_crWS', 'REVENUE', 'FUND_BALANCE_BP',
   'FUND_BALANCE_EP']

PRICE_crR and PRICE_crWS represent the prices for two different customer classes on the basis purely of cost recovery. The optimisation must seek to achieve cost recovery (first constraint in the code below) whilst observing a couple of key policy constraints which are represented by the second and third constraints in the code below.

This is what I have so far.

the objective function to minimise

finance_df['revenue_R'] = finance_df.apply(lambda row: row * row.DELIVERIES_R)

the constraints

cons = ({'type': 'ineq', 'fun': finance_df.apply(lambda row: row - row.price_crR, axis=1)},
    {'type': 'ineq', 'fun': finance_df.apply(lambda row: ((row * row.DELIVERIES_R) - row.OPEX_R + OTHER_REVENUE)\
                                            / (debt_CAPEX_ratio * row.debt_service), axis=1)},
    {'type': 'ineq', 'fun': finance_df.apply(lambda row: (1.05 * row.price_crR) - row, axis=1)})

non negativity constraints

bnds = ((0, None), (0, None))

series of initial best guesses

price_0 = [7, 7.5, 8, 8.5, 9, 9.5, 10]

the optimisation function

res = minimize(finance_df['revenue_R'], price_0, method='SLSQP', bounds=bnds, constraints=cons)

When running the above script I get the following error message:

    ("'Series' object has no attribute 'DELIVERIES_R'", 'occurred at index CAPEX_TOT')
Community
  • 1
  • 1
Brucey
  • 3
  • 2
  • 1
    `finance_df.apply(lambda row: row * row.DELIVERIES_R)`? You need to specify the axis like `df.apply(fun, 1)` axis 1 to get rows, else you get columns (axis 0). – Matteo Ferla Aug 15 '19 at 10:07

1 Answers1

0

The problem is caused by an incorrect value, finance_df.apply(lambda row: row * row.DELIVERIES_R). Unlike the iterating across a row (DataSeries), iterating across a table (DataFrame) requires the axis = 1 to be specified if row-wise, namely df.apply(fun, axis=1) else you get columns (axis 0) and as the column and the error you saw.

(Response first given as comment, now converted to answer to close quickly this typo question).

Matteo Ferla
  • 2,128
  • 1
  • 16
  • 27
  • Thank you! I fixed the typo and re-ran and I get the following error: 'Wrong number of items passed 21, placement implies 1' – Brucey Aug 15 '19 at 10:48
  • That means you are supposed to give one item, but you gave too many. I don't know where that is happening, but your 'fun' value in the constrain dictionary is not a callable but a DataSeries. Maybe there? – Matteo Ferla Aug 15 '19 at 11:06