Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

equivalent to R's `do.call` in python

Is there an equivalent to R's do.call in python?

do.call(what = 'sum', args = list(1:10)) #[1] 55
do.call(what = 'mean', args = list(1:10)) #[1] 5.5

?do.call
# Description
# do.call constructs and executes a function call from a name or a function and a list of arguments to be passed to it.
like image 453
Deena Avatar asked Aug 02 '16 14:08

Deena


People also ask

What is R operator in Python?

String Special Operators The syntax for raw strings is exactly the same as for normal strings with the exception of the raw string operator, the letter "r," which precedes the quotation marks. The "r" can be lowercase (r) or uppercase (R) and must be placed immediately preceding the first quote mark.

What is the def function in Python?

def is the keyword for defining a function. The function name is followed by parameter(s) in (). The colon : signals the start of the function body, which is marked by indentation. Inside the function body, the return statement determines the value to be returned.

Whats is do call?

call function. R has an interesting function called do. call. This function allows you to call any R function, but instead of writing out the arguments one by one, you can use a list to hold the arguments of the function.


3 Answers

There is no built-in for this, but it is easy enough to construct an equivalent.

You can look up any object from the built-ins namespace using the __builtin__ (Python 2) or builtins (Python 3) modules then apply arbitrary arguments to that with *args and **kwargs syntax:

try:
    # Python 2
    import __builtin__ as builtins
except ImportError:
    # Python 3
    import builtins

def do_call(what, *args, **kwargs):
    return getattr(builtins, what)(*args, **kwargs)

do_call('sum', range(1, 11))

Generally speaking, we don't do this in Python. If you must translate strings into function objects, it is generally preferred to build a custom dictionary:

functions = {
    'sum': sum,
    'mean': lambda v: sum(v) / len(v),
}

then look up functions from that dictionary instead:

functions['sum'](range(1, 11))

This lets you strictly control what names are available to dynamic code, preventing a user from making a nuisance of themselves by calling built-ins for their destructive or disruptive effects.

like image 81
Martijn Pieters Avatar answered Oct 17 '22 23:10

Martijn Pieters


do.call is pretty much the equivalent of the splat operator in Python:

def mysum(a, b, c):
    return sum([a, b, c])

# normal call:
mysum(1, 2, 3)

# with a list of arguments:
mysum(*[1, 2, 3])

Note that I’ve had to define my own sum function since Python’s sum already expects a list as an argument, so your original code would just be

sum(range(1, 11))

R has another peculiarity: do.call internally performs a function lookup of its first argument. This means that it finds the function even if it’s a character string rather than an actual function. The Python equivalent above doesn’t do this — see Martijn’s answer for a solution to this.

like image 35
Konrad Rudolph Avatar answered Oct 17 '22 22:10

Konrad Rudolph


Goes similar to previous answer, but why so complicated?

def do_call(what, args=[], kwargs = {}):
    return what(*args, **kwargs)

(Which is more elegant than my previously posted definition:)

def do_call(which, args=None, kwargs = None):
    if args is None and kwargs is not None:
        return which(**kwargs)
    elif args is not None and kwargs is None:
        return which(*args)
    else:
        return which(*args, **kwargs)

Python's sum is different than R's sum (1 argument a list expected vs. arbitraily many arguments expected in R). So we define our own sum (mysum) which behaves similarly to R's sum. In a similar way we define mymean.

def mysum(*args):
    return sum(args)

def mymean(*args):
    return sum(args)/len(args)

Now we can recreate your example in Python - as a reasonable 1:1 translation of the R function call.

do_call(what = mymean, args=[1, 2, 3])
## 2.0
do_call(what = mysum, args=[1, 2, 3])
## 6

For functions with argument names, we use a dict for kwargs, where the parameter names are keys of the dictionary (as strings) and their values the values.

def myfunc(a, b, c):
    return a + b + c

do_call(what = myfunc, kwargs={"a": 1, "b": 2, "c": 3})
## 6

# we can even mix named and unnamed parts
do_call(what = myfunc, args = [1, 2], kwargs={"c": 3})
## 6
like image 3
Gwang-Jin Kim Avatar answered Oct 17 '22 23:10

Gwang-Jin Kim