2016-01-02 126 views
0

我试图从Xlwings实验一些功能。我想使用允许快速插入的numpy的常用函数(numpy.interp)。在xlwings中加速UDF

@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行)的第三列,随机数bewteen 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 [...]值= 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 
+0

您是否尝试过并发现一些实际的性能问题? –

+0

确实如此。实际上,当我启动所有计算时,只要在VBA中运行(我想这是因为UDF被构建为在每个单元格上逐个运行)。也许如果我可以使用范围,它会更快,但我不知道如何轻松做到这一点。 – Coolpix

+0

[编辑]如果我可以得到活动单元格地址,我可以像Range(ActiveCell).table = ar一样使用数组和resut来做类似的事情? – Coolpix

回答

1

简短的回答是:使用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 

现在使用数组公式在Excel中所描述的hereCtrl+Shift+Enter)。

+0

非常感谢,这很好:)而且它非常快 – Coolpix

+0

我也试过类似的东西,但是我在Range.Value行上得到了“Erreur Automation”。 (xp,yp): “”“在矢量(xp,yp)上插值标量x”“” thisWB = xw.Workbook.active() thisSlctn = thisWB.get_selection(asarray = True) y = np.interp(x,xp,yp) thisSlctn.value = y – Coolpix

+0

'thisSlctn.xl_sheet.name'返回pywin32或appscript中的对象(取决于您的平台) 。你将不得不在你的示例中用'thisWB.name'替换它。 –