3

I've written a function that performs as a calculator. It works for the variables below.

However I want to scale it up to handle 15 different levels values, and 15 different sales and cost values. The function would apply different sales and cost calculations per level as below. (In that each calculation applies to a particular level, the calculations could potentially be defined outside the function.)

I could write numerous if/elif statements for each of the 15 levels, but that doesn't seem very Pythonic. Is there a method for programmatically scaling such a function to take many more sales, levels and costs?

For clarity's sake, the output would be the same as below (depending on the values entered of course) but the function should just be able to handle many more values.

levels_list = [4, 5]  # ultimately 15 values in this list

sale4 = 18280  # ultimately 15 of these values
sale5 = 19180
sale6 = 22170

cost1 = 224 # and 15 of these values
cost2 = 335
cost3 = 456

def sales(level, foo, bar):
    for level in levels_list: 
        if level == 4:
            x = cost1 + sale4 * foo
            y = cost2 + sale4 * bar
            z = x + y
        elif level == 5:  
            x = cost2 + sale5 * foo
            y = cost3 + sale5 * bar
            z = x + y
            return pd.DataFrame({'Total Cost':[z], 'x_Cost':[x], 'y_Cost':[y]})

sales(5, 10, 10)

    Total Cost  x_Cost  y_Cost
0   384391      192135  192256
RDJ
  • 3,182
  • 6
  • 31
  • 50

3 Answers3

3

Rather than using separate variables for each of your costs and sales, you should probably combine them into a list for each, or a dictionary, depending on the possible values for level. Depending on how your logic works for what costs are relevant for what levels, this may allow you to access the appropriate cost and sales entries based on the value of level

StephenTG
  • 2,449
  • 3
  • 23
  • 35
  • 1
    if the lowest level isn't 0 then the indices of the list would fall apart (especially if level can be negative), it may be better to use a dictionary even if all the keys are integers – Tadhg McDonald-Jensen Mar 01 '16 at 22:06
2

it would make sense to use a dict to associate the relevant values with each level:

levels_dict = {4 :(sale4, cost1, cost2),
               5 :(sale5, cost2, cost3)}

This way levels_dict[level] will give you the sale and two costs to use in calculations:

def sales(level, foo, bar):
    sale, x_cost, y_cost = levels_dict[level]
    x = x_cost + sale * foo
    y = y_cost + sale * bar
    ...

If level in range(15) is always true then using a list would remove the need for keys and you could use a list:

levels_data =  [None, #0
                None, #1
                None, #2
                None, #3
                (18280, 224, 335),
                (19180, 335, 456)]

although if level starts at 4 then this requires many place holders.

It also might be preferable to use a namedtuple to ensure you always put the values in the correct order:

import collections

level = collections.namedtuple("level",["sale","xcost","ycost"])

levels_dict = {4 :level(sale4, cost1, cost2),
               5 :level(sale5, cost2, cost3)}

This still works the same way as above but also lets you use the names instead of order:

def sales(level, foo, bar):
    data = levels_dict[level]
    x = data.xcost + data.sale * foo
    y = data.ycost + data.sale * bar
    ...
Tadhg McDonald-Jensen
  • 17,001
  • 3
  • 29
  • 51
  • Both the `dict` and the `namedtuple` solutions are perfect. Appreciate the comprehensive answer. – RDJ Mar 01 '16 at 23:12
1

Rather than multitests ,You can organize your data in a DataFrame, for exemple :

data=pd.DataFrame(np.array([[cost1,cost2,cost3],[sale4,sale5,sale6],
[cost2,cost3,cost4],[sale4,sale5,sale6]]).T,index=[3,4,5],
columns=   ['costx','salex','costy','saley'])

  costx  salex  costy  saley     
3   224  18280    335  18280
4   335  19180    456  19180
5   456  22170    512  22170

in such a way that each row is associated with a level. Then your function is immediate :

def sales(level, foo, bar):
        costx,salex,costy,saley=data.loc[level] 
        x = costx + salex * foo
        y = costy + saley * bar
        z = x + y
        return pd.DataFrame({'Total Cost':[z], 'x_Cost':[x], 'y_Cost':[y]})
B. M.
  • 16,489
  • 2
  • 30
  • 47