how to pass the parameters to apply correctly - python

There is an api function
get_next_trading_date(exchange='SZSE', date='2017-05-01')
and I have a DataFrame backTestRecordAfterModified showed as follow
when I run
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(func=get_next_trading_date, exchange='SZSE')
the console displayed the message : TypeError: get_next_trading_date() got multiple values for argument 'exchange'
so,how to pass the parameters correctly
supplementary
backTestRecordAfterModified['createdAt'] = backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date, exchange='SZSE'))
the code above still displays the same error.
i add the definition of get_next_trading_date
I got the final answer just now.
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date=date,exchange='SZSE'))

You'll have to use a lambda-function to pass the additional parameter to the get_next_trading_date() function:
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date=date, exchange='SZSE'))
The pandas.Series.apply() function does in fact support additional keyword arguments for the function, but the first argument to the function is always the value from the pandas series.
If get_next_trading_date() was defined differently, with the order of arguments reversed:
get_next_trading_date_2(date='2017-05-01', exchange='SZSE')
you could have used
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(func=get_next_trading_date, exchange='SZSE').

The apply function is called for each value of the pandas series, and the value is passed as an argument to the function by default.
The additional arguments you specify are passed after the series value.
So in your example, each time the function call would be like
get_next_trading_date(<i-th value of the series>, exchange='SZSE')
But in your function, the first argument is for exchange, so the <i-th value of the series> (current date) is passed to exchange and then there's another keyword argument trying to set the same variable. This causes the error. More in here.
Here you have two options.
a) Change the function definition to take date as first argument, so that you don't have to change your function call. But be sure to make the change everywhere you call this function.
get_next_trading_date(date='2017-05-01', exchange='SZSE')
b) Change your function call to pass date as second argument.
backTestRecordAfterModified['createdAt'] = backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date, exchange='SZSE'))
Or simplified as,
backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date, exchange='SZSE'), inplace=True)

One option is to use df.apply instead of series.apply:
df['createdAt'] = df.apply(lambda row: get_date(row['createdAt'], 'SZSE'), axis=1)
Or, if you don't want to pass the whole dataframe:
df['createdAt'] = [get_date(x, 'SZSE') for x in df['createdAt'].values]

Related

Creating an empty DataFrame as a default parameter

I am trying to create a python function that plots the data from a DataFrame. The parameters should either be just the data. Or the data and the standard deviation.
As a default parameter for the standard deviation, I want to use an empty DataFrame.
def plot_average(avg_df, stdev=pd.DataFrame()):
if not stdev.empty:
...
...
But implementing it like that gives me the following error message:
TypeError: 'module' object is not callable
How can an empty DataFrame be created as a default parameter?
for a default empty dataframe :
def f1(my_df=None):
if(my_df is None):
my_df = pd.DataFrame()
#stuff to do if it's not empty
if(len(my_df) != 0):
print(my_df)
elif(len(my_df) == 0):
print("Nothing")
A DataFrame is mutable, so a better approach is to default to None and then assign the default value in the function body. See https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
The problem lies not in the creation of a new DataFrame but in the way the function was called. I use pycharm scientific. In which I had the function call written in a block. Executing this block called the function which was, i presume, not compiled.
Executing the whole programm made it possible to call the function

Function executes either the key is there or not in dictionary.get in python 2.7

I am working with dictionaries in Python and I am searching for a value using:
my_dictionary_object.get("key")
As we all know if the key is missing in dictionary, it will return None object.
So to save extra line and to make my code more interesting I am trying:
def my_function():
'''do some calculations'''
return missing_value_from_dictionary
Now here is the fun part; when I do
my_dictionary_object.get("key", my_function())
it executes the function whether the key is missing or not so I thought let's remove the brackets and I did:
my_dictionary_object.get("key", my_function)
and (just in case)
my_dictionary_object.get("key", lambda: my_function())
but the one without lambda didn't execute (because it was never called) same happened with the one with lambda.
TL;DR
My question is why is the function get executed if the key is present in the dictionary?
Is it something that I am doing wrong or something I am missing here?
In: my_dictionary_object.get("key", my_function()) the execution looks something like:
Evaluate the first argument ("key")
Evaluate the second argument which is an expression: my_function(). So let's call the function, and use the return value in its place. Very much like in: a = my_function(), python would call the function and put the returned value in its place.
Call the mydictionary_object.get(..) with the above two evaluated arguments.
In other words, dictionary.get("key", default) will simply return the 2nd argument if the key doesn't exist. If it is a lambda, lambda is returned. A lambda is an object. Note that in .get("key", my_function()), my_function() is not technically the second argument. The resultant value returned as a result of execution of that function is the second argument -- which explains where you're wrong, hopefully.
What you are looking for is actually captured in another container called defaultdict.
What you'd do is:
from collections import defaultdict
my_dictionary_object = defaultdict(my_function) # my_function should not take any argument.
my_dictionary_object["non-existing-key"] # Magic happens, see below.
What happens is, if the key (=x) doesn't exist, my_function is called without any arguments and the dictionary is updated with the value returned by the function against the key (=x). Something like:
if "key" not in dictionary:
dictionary["key"] = my_function()
return dictionary["key"]

using = sign in function parameter in python

What is the use of = sign in following function in python
res=cv2.bitwise_and(frame,frame,mask=mask)
why we need mask= mask in it?
Thanks you
In Python you can define the optional parameters like:
def func(par, mask=1):
pass
and when you call the func function you can optionally specify the parameter mask.
func(2,mask=2)
lets assume you have mask variable that has been assigned value before you call func function
you can call like this
func(2,mask=mask)
back to your question the reason we have to specify mask=mask and not just call the function like func(2,3) is we may have more than one optional parameters like
def func2(par1,opt1=1,opt2=3):
pass
Here when you call func2 and want to pass value for par1 and opt2 You have to call like this func2(2,opt2=5)
The first mask is a variable defined in the function definition. The second mask is an argument which you are passing to the function. The = is there because the function definition must require it to be there as it's a default argument.
You can use it for explicit defenition of function's parameter.
For example you have next function defenition:
def add_action(action,time=datetime.now, mode=0):
In this function time and mode have predefined values(because this values can be most frequent uses for this function), and in cases where you have to change this predefined values you can only send them in needed direction:
add_action(action, datetime(2017, 08, 19), 1)
or send via their names, if you want to redefine only 1 parameter:
add_action(action, mode=2)
So, time would have the predefined value.
Also you can write function like:
def foo(par1, **kwargs)
Here par1 is obligatory parameter, and other parameters that you will send to function via names, will be in **kwargs that actualy is key word dictionary.
So if you invoke next function:
foo(value1, mode=1, date=now(), message='Hello')
In function body **kwargs will have next value:
{
mode:1,
date:datetime(2017, 08, 19, 14, 24, 56, 22393),//result of function now()
message:'Hello'
}

Python - Passing Functions with Arguments as Arguments in other Functions

I'm new to programming and I've been stuck on this issue and would really like some help!
One of the parameters in my function is optional, but can take on multiple default values based on another function. Both functions take in the same input (among others). When I try to assign a default using the function as illustrated below:
def func(foo):
# returns different values of some variable k based on foo
def anotherFunc(foo, bar, k=func(foo)):
# this is the same foo input as the previous function
I get the following error:
NameError: name 'foo' is not defined
The thing is, the user can call 'anotherFunc' with any value of 'k' they want, which complicates things. Is there any way to have a function with arguments in it as a parameter in another function? Or is there any way for me to set multiple default values of 'k' based on the previous function while still allowing the user to choose their own 'k' if they wanted?
Thanks!
foo at the moment of defining the function acts as placeholder for the first function argument. It has no value until the function is called, for which its value can be accessed in the function body, like so:
def another_func(foo, bar, k=None):
if k is None:
k = func(foo)
...
You would probably want to do something like:
def func(foo):
return foo
def anotherfunc(foo, bar, k=None):
if k == None:
k = func(foo)
#process whatever

passing the values to a function

I have a function that returns the replaced values correctly, but for some reason, the run_instances function receives the entire string as a single object (instead of 4 separate values).
import boto
ec2_conn = boto.connect_ec2(aws_access_key_id='XXX', aws_secret_access_key='XXX')
ami='ami-XXX'
key_name='XXX15a.pem'
instance_type='t1.macro'
aid="image_id='%s', placement='us-east-1a', key_name='%s', instance_type='%s'" % (ami, key_name, instance_type)
When I try to execute the run_instances function...
ec2_conn.run_instances(aid)
<Message>Invalid id: "image_id='ami-XXX', placement='us-east-1a', key_name='XXX.pem', instance_type='t1.macro'" (expecting "ami-...")</Message>
Is there any way to pass the values to the function correctly?
Simplifying the problem statement to: how to pass multiple variables around so they can be passed into a function later on without passing all variables individually...:
params = dict(ami='ami-XXX', key_name='XXX15a.pem', instance_type='t1.macro', placement='us-east-1a')
ec2_conn.run_instances(**params)
Store them in a dict and expand them to keyword arguments with **.

Categories

Resources