NumPy与MATLAB

2024-06-28 20:20:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经开始使用NumPy而不是MATLAB来处理很多事情,而且对于大多数事情来说,它似乎要快得多。我刚刚尝试用Python复制一段代码,但是速度要慢得多。我想知道两个都懂的人能不能看看,看看为什么会这样

纽比:

longTicker = np.empty([1,len(ticker)],dtype='U15')
genericTicker = np.empty([len(ticker)],dtype='U15')
tickerType = np.empty([len(ticker)],dtype='U10')
tickerList = np.vstack((np.empty([2,len(ticker)],dtype='U30'),np.ones([len(ticker)],dtype='U30')))
tickerListnum = 0
modelList = np.empty([2,9999],dtype='U2')
modelListnum = 0
derivativeType = np.ones(len(ticker))

for l in range(0,len(ticker)):
    tickerType[l] = 'Future'

    if not modCode[l] in list(modelList[1,:]):
        modelList[0,modelListnum] = modelListnum + 1
        modelList[1,modelListnum] = modCode[l]
        modelListnum += 1

    if ticker.item(l).find('3 MONTH') >= 0:
        x = list(metalTicks[:,0]).index(ticker[l])
        longTicker[0,l]  = metalTicks[x,3]
        if not longTicker[0,l] in list(tickerList[1,:]):
            tickerList[0,tickerListnum] = tickerListnum + 1
            tickerList[1,tickerListnum] = longTicker[0,l] 
            tickerList[2,tickerListnum] = 4
            tickerListnum += 1

        derivativeType[l] = 4
        tickerType[l] = 'Future'

    if ticker.item(l).find('CURNCY') >= 0:
        if ticker.item(l).find('KRWUSD CURNCY'):
            prices[l] = 1/float(prices.item(l))

        longTicker[0,l]  = ticker[l,0]
        if not longTicker[0,l] in list(tickerList[1,:]):
            tickerList[0,tickerListnum] = tickerListnum + 1
            tickerList[1,tickerListnum] = longTicker[0,l] 
            tickerList[2,tickerListnum] = 2
            tickerListnum += 1

        derivativeType[l] = 2
        tickerType[l] = 'FX'    

    if ticker.item(l).find('_') >= 0:
        x = ticker[l] == sasTick
        longTicker[0,l]  = bbgTick[x]
        if not longTicker[0,l] in list(tickerList[1,:]):
            tickerList[0,tickerListnum] = tickerListnum + 1
            tickerList[1,tickerListnum] = longTicker[0,l] 
            tickerList[2,tickerListnum] = 3
            tickerListnum += 1

        derivativeType[l] = 3
        tickerType[l] = 'Option'

    # need convert ticker thing    

    if not longTicker[0,l] in list(tickerList[1,:]):
            tickerList[0,tickerListnum] = tickerListnum + 1
            tickerList[1,tickerListnum] = longTicker[0,l] 
            tickerList[2,tickerListnum] = 1
            tickerListnum += 1

MATLAB代码:

^{pr2}$

在这个例子中,MATLAB似乎快了大约100倍。Python中的循环慢得多吗?在


Tags: inlenifnpnotitemlistempty
1条回答
网友
1楼 · 发布于 2024-06-28 20:20:57

虽然我不能确定是什么是导致减速的主要原因,但我确实注意到了一些会导致减速、易于修复并会导致代码更干净的事情:

  1. 从numpy数组到列表进行了大量转换。类型转换很昂贵,尽可能避免转换。在你的情况下,你所做的很少从纽姆身上获益。在几乎所有的情况下,最好只使用列表来代替1D数组,或者使用列表来代替2D数组。这更接近于MATLAB中的单元数组,只是它们可以动态调整大小并具有良好的性能。唯一可能的例外是sastickbbgtick,和{},后两种情况都很好。对于其他情况,如果您只是以增量方式放置值,则只需创建空列表并使用append;对于需要使用None或空字符串''访问任意元素预分配的情况。对于tickerList来说,有两个列表可能更容易。在
  2. 给unicode数组分配了很多整数。这还涉及类型转换(整数到unicode)。如果使用列表,这也不是问题。在
  3. 你经常使用foo.item(l)。这会将numpy元素转换为普通的python数据类型。同样,这是一个类型转换,所以如果可以避免的话,不要这样做。如果您遵循我的建议1并使用列表,那么在当前代码中就不需要这样做了。在
  4. 在MATLAB版本中有continue语句,但在python版本中没有,这意味着您在python版本中执行计算,而在MATLAB版本中则跳过。我认为使用if..elseif更好,但是{}也可以在Python中工作。在
  5. 循环range(0,len(ticker)),然后多次提取ticker元素。您最好直接在ticker上循环,例如for i, iticker in enumerate(ticker):。使用enumerate还可以跟踪索引。在
  6. 您可以使用find来确定子字符串是否在给定字符串中。使用in可以更快、更清晰、更简单。仅当您关心子字符串在哪里找到时才使用find,而您并不关心
  7. {{cd21>给一个数组赋值,然后给它赋值两次。在MATLAB版本中,首先递增,然后分配已经增加的版本。这涉及到在Python中执行相同的数学运算的频率是在MATLAB中的两倍。在
  8. tickerType预先分配给'Future'会更快,就像您在MATLAB中所做的那样,这可以通过使用tickerType = ['Future']*len(ticker)这样的方法来实现。在
  9. 因为tickerListnum和{}总是等于索引,所以根本没有理由拥有它们。把他们扔了吧。在
  10. 因为在tickerList的第一行中每个值只有一个实例,所以使用OrderedDict,或者使用常规的dict,如果不关心顺序,其中的键是longTicker值,而值是类型号,则会更快更容易使用。在
  11. 如果您不关心modelList的顺序,那么使用set会更快。在

所以这里有一个更快的版本,假设metalTickstickerList是列表列表,sasTick是numpy数组,prices和{}是列表或数组,假设您关心modelList和{}的顺序:

from collections import OrderedDict

longTicker = [None]*len(ticker)
tickerType = ['Future']*len(ticker)
tickerList = OrderedDict()
modelList = []
derivativeType = np.ones_like(ticker)

for i, (iticker, imodCode)  in enumerate(zip(ticker, modCode)):
    if imodCode not in modelList:
        modelList.append(imodCode)

    if '3 MONTH' in iticker:
        x = metalTicks[0].index(iticker)
        longTicker[i] = metalTicks[3][x]
        derivativeType[i] = 4

    elif 'CURNCY' in iticker:
        if 'KRWUSD CURNCY' in iticker:
            prices[i] = 1/prices[i]

        longTicker[i]  = iticker
        derivativeType[i] = 2
        tickerType[i] = 'FX'    

    elif '_' in iticker:
        longTicker[i]  = bbgTick[iticker == sasTick]
        derivativeType[i] = 3
        tickerType[i] = 'Option'

    tickerList[longTicker[i]] = derivativeType[i]

如果您不关心modelListtickerList的顺序,可以这样做:

^{pr2}$

或者更简单:

longTicker = [None]*len(ticker)
tickerType = ['Future']*len(ticker)
derivativeType = np.ones_like(ticker)

for i, iticker in enumerate(ticker):
    if '3 MONTH' in iticker:
        x = metalTicks[0].index(iticker)
        longTicker[i] = metalTicks[3][x]
        derivativeType[i] = 4

    elif 'CURNCY' in iticker:
        if 'KRWUSD CURNCY' in iticker:
            prices[i] = 1/prices[i]

        longTicker[i]  = iticker
        derivativeType[i] = 2
        tickerType[i] = 'FX'

    elif '_' in iticker:
        longTicker[i]  = bbgTick[iticker == sasTick]
        derivativeType[i] = 3
        tickerType[i] = 'Option'

modelList = set(modCode)
tickerlist = dict(zip(longTicker, derivativeType))

相关问题 更多 >