scipy.minimize : how to include a static data in the function - python-3.x

I try to generalize an optimization function using scipy.optimize.
Actually I write this function in this way:
def value_to_optimize(data):
data_set = np.genfromtxt('myfilepathinstaticmode', delimiter=',',skip_header=1)
doe = data_set[:,:-1]
new_data_set = np.vstack((np.array(doe),np.array(data)))
return result_of_another_function(new_data_set)
def new_data():
rst = minimize(value_to_optimize,[0,0])
return rst.x
the function I try to optimize is the first one. And to do that I use the second function that use "minimize" and a x0 for starting optimization.
As you can see my problem is comming from 'myfilepathinstaticmode'. I would like to generalize my function, like value-to_optimize(filename,data), but at this moment, I cannot apply optimize() on it because it is only working on numbers.
Any idea on how to write it in a generalized manner ?

I personally would read the data outside of the minimizer function and then hand over only that data into the method:
def value_to_optimize(data, doe):
new_data_set = np.vstack((np.array(doe),np.array(data)))
return result_of_another_function(new_data_set)
def new_data():
data_set = np.genfromtxt('myfilepathinstaticmode', delimiter=',',skip_header=1)
doe = data_set[:,:-1]
rst = minimize(value_to_optimize, ([0,0], doe))
return rst.x
EDIT: I'm not sure if I understood your question correctly. So, alternatively, a more flexible approach would be to use functools.partial to generate a method with the filename as a parameter which you can then hand over to your optimizer.

Something is working in this way. I'm not convinced about the robustess of the code. The solution: I defined the function value_to_optimize() inside the function new_data(). Like this, the parameter 'filename' is out of "value_to_optimize()" but is a kind of "global" assignment inside new_data().
def new_data(filename):
def value_to_optimize(data):
data_set = np.genfromtxt(filename, delimiter=',',skip_header=1)
doe = data_set[:,:-1]
new_data_set = np.vstack((np.array(doe),np.array(data)))
return result_of_another_function(new_data_set)
rst = minimize(value_to_optimize,[0,0])
return rst.x

Related

Python function return type hints with fixed dictionary keys

I have a function which returns a dictionary that always has the same keys (send over network and "stringified" with json). And basically my function looks like this:
def getTemps(self) -> dict:
"""
get room and cpu temperature in °C as well as humidity in %
"""
# send temperature request to server
msg = {'type':'req', 'reqType':'temps'}
self.send(msg)
res = self.recieve() # get response
return res
and the dictionary you get from this function always looks something like that:
{'Room':float, 'CPU':float, 'hum':float}
so I was wondering if there was a way to specify the return type of the function so you know what keys the dictionary has:
def getTemps(self) -> Dict['Room':float, 'CPU':float, 'hum':float]
but that didn't work as it only showed Dict[slice, slice, slice] when hovering over the function (I am using vscode).
I don't think this is something that is very useful, but something that makes your code look better and also be easier to use for someone else. So if someone knows if this is possible and how, I would be very grateful to get a response!
consider this:
class Message:
def __init__(self,room,cpu,hum):
self.Room = room
self.CPU = cpu
self.hum = hum
and return Message(room,cpu,hum) or define a method to convert this to dict in the class if necessary.
This may be the only method.
Update: This is neither the only nor the best method, see comments.

.get_dummies() works alone but doesnt save within function

I have a dataset and I want to make a function that does the .get_dummies() so I can use it in a pipeline for specific columns.
When I run dataset = pd.get_dummies(dataset, columns=['Embarked','Sex'], drop_first=True)
alone it works, as in, when I run df.head() I can still see the dummified columns but when I have a function like this,
def dummies(df):
df = pd.get_dummies(df, columns=['Embarked','Sex'], drop_first=True)
return df
Once I run dummies(dataset) it shows me the dummified columsn in that same cell but when I try to dataset.head() it isn't dummified anymore.
What am I doing wrong?
thanks.
You should assign the result of the function to df, call the function like:
dataset=dummies(dataset)
function inside them have their own independent namespace for variable defined there either in the signature or inside
for example
a = 0
def fun(a):
a=23
return a
fun(a)
print("a is",a) #a is 0
here you might think that a will have the value 23 at the end, but that is not the case because the a inside of fun is not the same a outside, when you call fun(a) what happens is that you pass into the function a reference to the real object that is somewhere in memory so the a inside will have the same reference and thus the same value.
With a=23 you're changing what this a points to, which in this example is 23.
And with fun(a) the function itself return a value, but without this being saved somewhere that result get lost.
To update the variable outside you need to reassigned to the result of the function
a = 0
def fun(a):
a=23
return a
a = fun(a)
print("a is",a) #a is 23
which in your case it would be dataset=dummies(dataset)
If you want that your function make changes in-place to the object it receive, you can't use =, you need to use something that the object itself provide to allow modifications in place, for example
this would not work
a = []
def fun2(a):
a=[23]
return a
fun2(a)
print("a is",a) #a is []
but this would
a = []
def fun2(a):
a.append(23)
return a
fun2(a)
print("a is",a) #a is [23]
because we are using a in-place modification method that the object provided, in this example that would be the append method form list
But such modification in place can result in unforeseen result, specially if the object being modify is shared between processes, so I rather recomend the previous approach

How to return a variable from a python function with a single parameter

I have the following function:
def test(crew):
crew1 = crew_data['CrewEquipType1']
crew2 = crew_data['CrewEquipType2']
crew3 = crew_data['CrewEquipType3']
return
test('crew1')
I would like to be able to use any one of the 3 variables as an argument and return the output accordingly to use as a reference later in my code. FYI, each of the variables above is a Pandas series from a DataFrame.
I can create functions without a parameter, but for reason I can't quite get the concept of how to use parameters effectively such as that above, instead I find myself writing individual functions rather then writing a single one and adding a parameter.
If someone could provide a solution to the above that would be greatly appreciated.
Assumption: You problem seems to be that you want to return the corresponding variable crew1, crew2 or crew3 based on your input to the function test.
Some test cases based on my understanding of your problem
test('crew1') should return crew_data['CrewEquipType1']
test('crew2') should return crew_data['CrewEquipType2']
test('crew3') should return crew_data['CrewEquipType3']
To accomplish this you can implement a function like this
def test(crew):
if crew=='crew1':
return crew_data['CrewEquipType1']
elif crew=='crew2':
return crew_data['CrewEquipType2']
elif crew=='crew3':
return crew_data['CrewEquipType3']
...
... # add as many cases you would like
...
else:
# You could handle incorrect value for `crew` parameter here
Hope this helps!
Drop a comment if not

How can I make this body of code through a for loop?

So, I'm trying to get this code to work in a cleaner way, mainly, through the use of a for loop, but having a really hard time trying to do so. I haven't been able to make a loop that assigns each value of the dictionary to a correspondent variable, so it can be used in the class. For context, the dictionary contains values obtained from another class, I just put those in the dict and sent it to this class, so I don't need to calculate those again.
def get_ipr_data(self):
self.reservoir_result_dict = ReservoirDataFrame.reservoir_result_dict
self.pb = self.reservoir_result_dict.get("pb")
self.rs = self.reservoir_result_dict.get("rs")
self.bo = self.reservoir_result_dict.get("bo")
self.uo = self.reservoir_result_dict.get("uo")
self.re = self.reservoir_result_dict.get("re")
self.j_index = self.reservoir_result_dict.get("j_index")
self.q_max = self.reservoir_result_dict.get("q_max")
self.pws = self.reservoir_result_dict.get("pws")
self.qb = self.reservoir_result_dict.get("qb")
You can use setattr function
for name in ["pb", "rs", "bo", "uo", "re", "j_index", "q_max", "pws", "qb"]:
setattr(self, name, self.reservoir_result_dict.get(name))
Documentation of setattr:
https://docs.python.org/3/library/functions.html#setattr
Delegating attributes is done by defining the __getattr__ method. You should store the dictionary only and then define __getattr__.
class Foo:
...
def get_ipr_data(self):
self.reservoir_result_dict = ReservoirDataFrame.reservoir_result_dict
def __getattr__(self, item):
return self.reservoir_result_dict[item]

How can I make objects with functions? (Turning a string into a object name)

I've just started learning Python recently and the first project I'm making is a text based adventure game however I've run into a problem. I need a function that makes more objects using the class Goblin that are named after a string.
def spawn(name):
title = name
exec("{0} = {1}".format('title', Goblin))
return title, 'spawn'
Essentially, another function calls this function to create another Goblin (a class) using the input name(a string) as the name of the new Goblin.
What I don't under stand though is that when I run the code(using "bill" as the argument), it gives me this error.
bill = <class '__main__.Goblin'>
^
SyntaxError: invalid syntax
Shouldn't my function be equivalent to:
bill = Goblin
When you do this:
exec("{0} = {1}".format('title', Goblin))
format method converts Goblin class by calling default __str__ method which yields <class '__main__.Goblin'>
Do this instead:
exec("{0} = {1}".format('title', 'Goblin'))
Wait! don't to this, just do:
title = Goblin
as it's strictly equivalent (without any security issues :)).
But that will just alias Goblin class to title. No real interest to all this after all (unless you want to create an instance?: title = Goblin())
With your comment: "I want a Goblin that is named after the string which title represents" I get it: you need
exec("{0} = {1}".format(title, 'Goblin()'))
(no quotes for the first arg so the name you're passing is used, and () on the second to create an instance)
Again: this is really a clumsy way of doing it. What if you want to iterate through all your goblins?
It would be much better to create a dictionary:
goblins_dict = dict()
goblins_dict["my_goblin"] = Goblin()
goblins_dict["my_goblin_2"] = Goblin()
and so on...

Resources