在 xlwings 中加速 UDF

Accelerate UDF in xlwings

我尝试了 Xlwings 的一些功能。我想使用 numpy 中的一个通用函数,它允许快速插值 (numpy.interp)。

@xlfunc
def interp(x, xp,yp):
    """Interpolate vector x on vector (xp,yp)"""
    y=np.interp(x,xp,yp)
    return y

@xlfunc
def random():
    """Returns a random number between 0 and 1"""
    x=np.random.randn()
    return x   

例如,我像这样创建两个向量 (xp, yp)(在 Excel 中) 800 行

First Column Second Column
0    =random()
1    =random()
2    =random()
3    =random()
4    =random()
5    =random()
[...]

在第三列我创建了另一个向量(60 行),随机数在 0 和 800 之间(按升序排列) 这给我这样的东西:

Third Column    
17.2    
52.6    
75.8    
[...]

我想将第三列插入到第一列中。所以

Fourth Column    
=interp(C1,A1:A800,B1:B800)    
=interp(C2,A1:A800,B1:B800)    
=interp(C3,A1:A800,B1:B800)    
[...]

这很容易做到。但是,如果我有 10 列或更多列进行插值,则可能会花费太多时间。我相信有更好的方法可以做到这一点。一个想法 ?

感谢您的帮助!

编辑:

我试过了,但在 "xw.Range[...].value=y"

上不起作用
@xw.xlfunc
def interpbis(x, xp,yp):
    """Interpolate scalar x on vector (xp,yp)"""
    thisWB=xw.Workbook.active()
    thisSlctn=thisWB.get_selection(asarray=True)
    sheet=thisSlctn.xl_sheet.name
    r = thisSlctn.row
    c = thisSlctn.column
    y=np.interp(x,xp,yp)
    xw.Range(sheet,(r,c)).value=y
    return None

简短的回答是:使用 Excel 的数组函数。

长答案是: 首先,更新到 xlwings v0.6.4(否则我要为 random() 展示的内容将不起作用)。然后按如下方式更改您的功能:

from xlwings import Application, Workbook, xlfunc
import numpy as np

@xlfunc
def interp(x, xp, yp):
    """Interpolate vector x on vector (xp,yp)"""
    y = np.interp(x, xp, yp)
    return y[:, np.newaxis]  # column orientation

@xlfunc
def random():
    """Returns a random number between 0 and 1"""
    app = Application(Workbook.caller())
    # We shall make this easier in a future release (getting the array dimensions)
    r = app.xl_app.Caller.Rows.Count
    c = app.xl_app.Caller.Columns.Count
    x = np.random.randn(r, c)
    return x

现在按照 here (Ctrl+Shift+Enter) 中所述使用 Excel 中的数组公式。