【问题标题】:Python: Create a multidimensional array by stacking a 1D array in a loopPython:通过在循环中堆叠一维数组来创建多维数组
【发布时间】:2019-04-19 12:28:01
【问题描述】:

自从我一直在解决这个问题以来已经有 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) 矩阵

【问题讨论】:

  • 你为什么使用np.append而不是列表追加?这样使用起来更快、更容易。
  • 因为我不知道列表追加。我一直认为numpy数组更快
  • 列表迭代更快,尤其是在构建新列表或数组时。 List append 只是添加一个指向列表的指针;它就地运行。 np.appendnp.concatenate 的覆盖函数,每次都会创建一个新数组(带有完整副本)。要获得正确的迭代连接,您必须密切关注维度。 np.array([]) 的形状为 (0,)。那只能与另一个一维数组连接。
  • np.empty(shape=[self.steps, self.sims]) 是一个 (self.steps, self.sims) 形状的数组,包含未指定的值。它不等同于empty 列表[]。您可以将它与另一个具有共享维度的二维数组连接起来,但结果仍然具有那些未指定的值。

标签: arrays python-3.x numpy


【解决方案1】:

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

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

【讨论】:

  • np.append 没有 axis 参数,将所有输入展平。所以你只是在构建一个长的平面阵列。最好查看 np.append 等函数的代码,看看它们最终会做什么。
【解决方案2】:

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

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)) 

【讨论】:

  • 如果我这样做 total[i,j] = sT 会在内部循环中工作吗?
猜你喜欢
  • 1970-01-01
  • 2014-06-26
  • 2018-09-26
  • 2021-02-01
  • 2011-05-28
  • 2019-11-16
  • 2018-06-12
  • 2015-03-14
  • 2020-05-15
相关资源
最近更新 更多