Python callable arguments from Excel

Many Scipy functions have “callable” arguments, i.e. functions that can be called, with the returned data used as input by the calling function. Types of callable arguments include:

  • Functions in the active Python module
  • Functions in any active loaded library
  • Lambda functions

When the callable argument is passed from Excel, using pyxll, the function name will be passed as a text string, which must be converted to a function object in the Python code. Different procedures are required for the three types of function listed above:

  • Functions in the active module can be called with the “globals” method (The globals () method returns the dictionary of the current global symbol table. )
  • Functions in active loaded libraries can be called with the “getattr” method (The getattr() method returns the value of the attribute of an object.)
  • Strings in lambda format can be converted to lambda functions with the eval() function

Examples of each of these methods are included in the code below:

import scipy as sp
import scipy.stats as stats
import numpy  as np

mods = {'np': np, 'stats': stats, 'sp': sp}

def GetCallable(func, mod = None):
    # Convert string to callable
    # Remove spaces and = from start of string
    func = func.replace('=', '')
    func = func.strip()
    
    # If string starts with 'lambda' convert ^ to **, then convert string to lambda function
    if func[0:6] == 'lambda':
        func = func.replace('^', '**')
        func = eval(func)
    # Else if module is not specified, convert string to function from globals
    elif mod is None:
        func = globals()[func]
    # or if mod is specified, convert mod string to module, then func string to function from mod 
    else:
        mod = mods[mod]
        func = getattr(mod, func)
    return func

The output from this function is a function object that can be passed to any function requiring callable arguments:

@xl_func
@xl_arg('x', 'numpy_array', ndim = 2)
@xl_arg('y', 'numpy_array', ndim = 2)
@xl_arg('rank', 'numpy_array<var>', ndim = 2)
@xl_arg('weigher', 'str')
@xl_arg('mod', 'str')
@xl_arg('additive', 'bool')
def py_weightedtau(x, y, rank = None, weigher = None, mod  = None, additive = None):
    """
Compute a weighted version of Kendall's :math:`\tau`.
   ...
Function argument descriptions
    ...
    """
    if weigher is not None: weigher = GetCallable(weigher, mod)
    
    kwargs = {'rank': rank, 'weigher': weigher, 'additive': additive}
    kwargs = {k:v for k,v in kwargs.items() if v is not None}

    return stats.weightedtau(x, y, **kwargs)[0]

This entry was posted in Excel, Link to Python, NumPy and SciPy, PyXLL, UDFs and tagged , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.