Python:通过在循环中堆叠一维数组来创建多维数组

时间:2019-04-19 12:28:02

标签: arrays python-3.x numpy

距离我研究此问​​题已有2天了,但无法突破。在下面的代码中,每次循环运行时,内部for循环都会创建pathwiseminS(252)的数组。

我想要的是当此循环结束时,将其堆叠在另一个数组中(逐行或逐列,任何有效的方法!)。最后,创建一个名为total的多维数组,该数组应该为(200,252)或(252,200)。

我尝试了np.concatenate,'np.vstack等,但是无法正确使用。

class pricing_lookback:
def __init__(self, spot, rate, sigma, time, sims, steps):
    self.spot = spot
    self.rate = rate
    self.sigma = sigma
    self.time = time
    self.sims = sims
    self.steps = steps
    self.dt = self.time / self.steps

def call_floatingstrike(self):

    simulationS = np.array([])
    simulationSt = np.array([])
    call2 = np.array([])
    total = np.array([])
    # total = np.empty(shape=[self.steps, self.sims])
    # total = np.empty(shape=self.steps,).reshape(self.steps)
    for j in range(self.sims):
        sT = self.spot
        pathwiseminS = np.array([])
        for i in range(self.steps):
            phi = np.random.normal()
            sT *= np.exp(
                (self.rate - 0.5 * self.sigma * self.sigma) * self.dt + self.sigma * phi * np.sqrt(self.dt))
            pathwiseminS = np.append(pathwiseminS, sT)
            total = pathwiseminS.copy()

        # print(np.shape(pathwiseminS))
        total = np.append([total],[total], axis=0)
        # np.hstack((total,pathwiseminS.transpose()))
        # print(np.size(b), np.shape(b))
        call2 = np.append(call2, max(pathwiseminS[self.steps - 1] - self.spot, 0))
        # print (pathwiseminS[self.steps-1])
        # print(call2)
        simulationSt = np.append(simulationSt, pathwiseminS[self.steps - 1])
        simulationS = np.append(simulationS, min(pathwiseminS))
    # print(b)
    call = max(np.average(simulationSt) - np.average(simulationS), 0)
    return call, total  # ,call2,

如果最后打印total,我会得到(2,252)矩阵

2 个答案:

答案 0 :(得分:0)

我的一个朋友解决了这个问题:基本上在返回时就重塑了数组。以下还有免费代码,用于为浮动回溯看涨期权定价。

class pricing_lookback:
def __init__(self, spot, rate, sigma, time, sims, steps):
    self.spot = spot
    self.rate = rate
    self.sigma = sigma
    self.time = time
    self.sims = sims
    self.steps = steps
    self.dt = self.time / self.steps

def call_floatingstrike(self):

    simulationS = np.array([])
    simulationSt = np.array([])
    call2 = np.array([])
    total = np.array([])
    for j in range(self.sims):
        sT = self.spot
        pathwiseminS = np.array([])
        for i in range(self.steps):
            phi = np.random.normal()
            sT *= np.exp(
                (self.rate - 0.5 * self.sigma * self.sigma) * self.dt + self.sigma * phi * np.sqrt(self.dt))
            pathwiseminS = np.append(pathwiseminS, sT)

        total = np.concatenate((total, pathwiseminS), axis=0)#This is add everything to one row
        call2 = np.append(call2, max(pathwiseminS[self.steps - 1] - self.spot, 0))
        simulationSt = np.append(simulationSt, pathwiseminS[self.steps - 1])
        simulationS = np.append(simulationS, min(pathwiseminS))

    call = max(np.average(simulationSt) - np.average(simulationS), 0)
    return call, total.reshape(self.sims, self.steps)# This transforms it to expected matrix

答案 1 :(得分:0)

这是从列表列表构建数组的典型方法:

In [127]: alist = [] 
     ...: for i in range(3): 
     ...:     sublist = [] 
     ...:     for j in range(4): 
     ...:         sublist.append(i*10+j) 
     ...:     alist.append(sublist) 
     ...:                                                                            
In [128]: alist                                                                      
Out[128]: [[0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]]
In [129]: np.array(alist)                                                            
Out[129]: 
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23]])

我尝试用concatenates复制列表追加方法,但不断遇到类似错误

ValueError: all the input arrays must have same number of dimensions
ValueError: all the input array dimensions except for the concatenation axis must match exactly

In [130]: arr = np.zeros((0,4), int) 
     ...: for i in range(3): 
     ...:     arr1 = np.zeros((0),int) 
     ...:     for j in range(4): 
     ...:         arr1 = np.concatenate((arr1, np.array([i*10+j]))) 
     ...:     arr = np.concatenate((arr, arr1), axis=0) 

我最终可以正确确定尺寸,但这不值得我花时间。

最快,非迭代的方法类似于:

In [133]: np.arange(4)+10*np.arange(3)[:,None]                                       
Out[133]: 
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23]])

如果必须进行迭代,则创建合适大小的空白数组并分配值会更容易:

In [135]: arr = np.zeros((3,4),int) 
     ...: for i in range(3): 
     ...:     for j in range(4): 
     ...:         arr[i,j] = 10*i+j 
     ...: arr                                                                        
Out[135]: 
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23]])

后一种方法的速度与列表追加方法相当。


清理了concatenate版本。

arr将在每一步为2d(n,4)。

arr1在每一步均为1d(m);必须将其扩展为2d才能与arr串联。

In [158]: arr = np.zeros((0,4), int) 
     ...: for i in range(3): 
     ...:     arr1 = np.zeros((0,),int) 
     ...:     for j in range(4): 
     ...:         arr1 = np.concatenate((arr1, np.array([i*10+j]))) 
     ...:     arr = np.concatenate((arr, arr1[None,:]), axis=0) 
     ...:                                                                            
In [159]: arr                                                                        
Out[159]: 
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23]])

np.append只是concatenate,可确保输入至少为1d。因此我们可以在内部循环中使用它。 np.vstack确保其输入为2d,因此我们可以在外部循环中使用它。这些只是隐藏细节。他们不会改变速度。

In [161]: arr = np.zeros((0,4), int) 
     ...: for i in range(3): 
     ...:     arr1 = np.zeros((0,),int) 
     ...:     for j in range(4): 
     ...:         arr1 = np.append(arr1, i*10+j) 
     ...:     arr = np.vstack((arr, arr1))