将数组广播到不同的形状(添加“假”尺寸)

时间:2013-02-03 02:49:43

标签: python arrays numpy fortran numpy-broadcasting

在python中(使用numpy),我可以将数组广播到不同的形状:

>>> import numpy as np
>>> a = np.array([2,3,4])
>>> b = np.zeros((3,2))
>>> b[:,:] = np.zeros((3,2))
>>> b[:,:] = a[:,np.newaxis]  #<-- np.newaxis allows `a` to be "broadcasted" to the same shape as b.
>>> b
array([[ 2.,  2.],
       [ 3.,  3.],
       [ 4.,  4.]])
>>> c = np.zeros((2,3))
>>> c[:,:] = a[np.newaxis,:]
>>> c
array([[ 2.,  3.,  4.],
       [ 2.,  3.,  4.]])

有没有办法在 fortran 中达到同样的效果?我有一个子程序,希望传入2D数组 - 我想将我的1-D阵列“广播”到2-D,如上所述。由于它似乎很重要,我的2D数组确实有一个显式接口。

作为旁注,我认为此功能可能reshape内在提供, - 类似于:

real,dimension(3) :: arr1d
reshape(arr1d, (/3,3/), order=(/1,/1))

但在阅读完文档之后,我认为这是不可能的,因为order似乎需要将所有数字1包含在“N”中。

编辑:为了更清楚一点,我正在寻找一种简单的方法来在输入a上创建几个变换,以便:

案例1

b(i,j) .eq. a(i)  !for all j, or even just j=1,2

案例2

b(j,i) .eq. a(i)  !for all j, or even just j=1,2
任意维度的

奖励积分 1

b(i,j,k) .eq. a(i,j)
b(i,k,j) .eq. a(i,j)

1 免责声明 - 我实际上没有SO超能力给回答者提供奖励积分; - )

2 个答案:

答案 0 :(得分:6)

我不确定你要完成什么,但这里有几个可能有用的片段。

reshape可以使用一个名为pad的可选参数,该参数可用于提供重塑为数组所需的“额外”元素,这些元素的元素比您开始时多,例如3x4到2x4x2。

你可能也对spread函数感兴趣,该函数是为'upranking'数组而设计的,它采用了一个n级数组并输出了一个n + 1级数组。第二个副本中的片段可以重写为

array2d = spread(array1d,2,2)

在此示例中,第二个参数是用于传播第一个参数以进行输出的维度。第三个参数是要输入的数组的副本数。

PS对spread的调用应该是spread(array1d,1,2),我还没有检查过。

编辑以回应OP编辑问题

通过分别在尺寸2和1上展开来满足两种情况1和2。在Fortran

b = spread(a,2,j)

b = spread(a,1,j)

由于spread返回排名1大于其第一个参数的排名的数组,因此它提供了所寻求的任意维度。但是,因为显示排名3及以上的阵列非常耗费空间,所以我不会这样做。

答案 1 :(得分:1)

重塑内在函数允许您将1D数组复制到2D数组。使用最新的Fortran编译器,它们是一种指针技术。指针提供第二种引用存储的方式,避免复制。该方法是“指针边界重新映射”。一个例子:

program array_tst

  integer, dimension (4), target :: array_1d
  integer, dimension (:,:), pointer :: array_2d

  array_1d = [ 1, 2, 3, 4 ]

  array_2d (1:2, 1:2) => array_1d

  write (*, *) array_2d (1,1), array_2d (1,2), array_2d (2,1), array_2d (2,2)

end program array_tst

另见changing array dimensions in fortran

P.S。回复评论...如果你不介意复制数组,这里是如何使用重塑:

program array_reshape

  integer, dimension (4) :: array_1d
  integer, dimension (2, 2) :: array_2d

  array_1d = [ 1, 2, 3, 4 ]

  array_2d = reshape ( array_1d, [2,2] )

  write (*, *) array_2d (1,1), array_2d (1,2), array_2d (2,1), array_2d (2,2)

end program array_reshape