如何将相同长度的1D ndarrays的1D numpy.ndarray转换为2D numpy.ndarray?

rqdpfwrv  于 2023-05-22  发布在  其他
关注(0)|答案(2)|浏览(129)

我遇到了一个问题,一个ndarray,与相同长度的1d ndarrays作为元素,不能优雅地转换为2d ndarray。数组就像这样:

[array([ 1.24836708, -0.00366597, -0.00617445,  0.00593824, -0.00499844,
        -0.008723  ,  0.0017313 ,  0.0032415 , -0.00921341, -0.08843152,
        -0.7156603 , -1.36149851,  1.03884429, -1.07907692, -1.08093478,
         0.40311199,  1.69189478])
 array([ 1.25213268e+00,  5.91834461e-06, -3.67174629e-03,  4.31587243e-03,
         2.05513245e-03,  4.03030160e-03, -3.70626458e-03, -3.19801204e-03,
        -4.03959450e-03, -3.16571953e-04, -3.36570170e-03,  4.23967454e-03,
        -4.80364918e-03, -5.40294083e-05, -7.57197110e-04,  8.55342504e-04,
         8.52148544e-06])
 array([  1.22506234,  -0.6000973 ,  -0.65958838,   0.01343306,
         -0.28506279,  -0.64566119,  -0.02085904,  -0.18191512,
         -2.45525694,  -1.91504442, -10.        , -10.        ,
          0.28079188,   2.70344181, -10.        ,  -4.4974326 ,
          4.82187824])
 ...

数组的形状为(256,)(批量大小)。它似乎不被识别为2d数组,对吗?代码如下:

def sample(self, batch_size, **kwargs):
        """
        Sample a batch of experiences.
        Args:
            batch_size: int
                How many experience tuples to sample as a batch.
        Returns:
            state_batch: np.ndarray
                batch of current observed states
            action_batch: np.ndarray
                batch of actions executed given current states
            reward_batch: np.ndarray
                rewards received as results of executing action_batch
            next_state_batch: np.ndarray
                next state observed after executing action_batch
            done_mask: np.ndarray
                done_mask[i] = 1 if executing act_batch[i] resulted in the end of an episode
            discount: np.ndarray
                product of gammas for N-step returns
        """
        assert len(self._buffer) >= batch_size
        
        idx = np.random.randint(0, len(self._buffer), size=batch_size)
        batch = np.array(self._buffer)[idx]

        weights = np.zeros(batch_size)
        idxes = np.zeros(batch_size)

        return [np.array(batch[:, i]) for i in range(6)] + [weights, idxes]

self._buffer是一个列表,其中[list(len=17), list(len=6), int, list(len=17), bool, int]是元素。我问的数组实际上是np.array(batch[:, 0])
我尝试了np.array,array.reshape,但没有成功。我能想到的唯一方法是将数组展平,然后重新塑造它。
是否有任何方法可以将数组转换为一个'常见'的二维数组如下几个步骤?

[ 1.28988438e+00 -3.28926461e-01 -3.16421640e-01  8.41842633e-03
 -6.04719630e-01 -3.21522510e-01  2.62200694e-02 -6.86004568e-01
 -2.75207792e+00  7.86307393e-01 -1.00000000e+01 -1.00000000e+01
  3.95934592e-01 -6.10089078e+00 -1.00000000e+01  5.53911043e-02
 -9.57694240e+00]
[ 1.20355496 -0.08770949  0.02464436 -0.11603001  1.19935722 -0.01665168
 -0.13457423 -0.03690821 -1.60970334  0.07964383 -5.48408598  0.10511611
 -8.75844077 -6.11991489 -2.52924686 -4.49214368  1.07501073]
[ 1.23668679e+00  1.71734326e-02  1.66840531e-02  5.26031800e-03
 -2.82087376e-02 -3.94339947e-03  2.50997621e-02  8.48180561e-02
  1.36369562e-01 -5.52168069e-01  6.43659328e-01  5.59083718e-01
  9.81923803e-03  1.00000000e+01  2.63192025e-01  8.68684414e-01
 -4.33114962e+00]
 ...
2guxujil

2guxujil1#

好吧,看起来问题是由于numpy数组中内部列表的长度或数据类型不一致。要将等长的1D numpy数组列表转换为2D numpy数组,您可以简单地使用np.stack或np.vstack。下面是如何使用它:

# Suppose lst is your list of 1D numpy arrays
# Convert it into a 2D numpy array
two_d_array = np.stack(lst)

two_d_array = np.vstack(lst)

如果你将它应用到你的当前代码中,它看起来像这样:

def sample(self, batch_size, **kwargs):
assert len(self._buffer) >= batch_size

idx = np.random.randint(0, len(self._buffer), size=batch_size)
batch = np.array(self._buffer)[idx]

weights = np.zeros(batch_size)
idxes = np.zeros(batch_size)

# Here, instead of creating a list of arrays, we create a 2D array
return [np.vstack(batch[:, i]) for i in range(6)] + [weights, idxes]

这将把你的batch转换成一个2D numpy数组,假设每个batch[:,i]条目都是一个长度相等、类型兼容的1D numpy数组列表。如果长度或类型不兼容,则需要先解决这些问题,然后才能将列表转换为2D numpy数组。

yzuktlbb

yzuktlbb2#

让我们专注于从数组列表中创建数组。

In [93]: alist = [np.arange(3)+i for i in range(4)]
In [94]: alist
Out[94]: [array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4]), array([3, 4, 5])]

如果这些数组确实具有相同的大小,您将得到一个数字2d数组-这是np.array的首选操作。

In [95]: np.array(alist)
Out[95]: 
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4],
       [3, 4, 5]])

但是如果一个(或多个)数组不同,我们会得到一个错误:

In [96]: alist[3] = np.arange(2)    
In [97]: np.array(alist)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[97], line 1
----> 1 np.array(alist)

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (4,) + inhomogeneous part.

根据numpy版本的不同,它可能只是给予对象dtype数组,或者发出警告,或者像最新版本一样需要我们进行更改。

In [102]: foobar = np.array(alist, object)    
In [103]: foobar
Out[103]: 
array([array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4]),
       array([0, 1])], dtype=object)

此为1d对象dtype,而不是2d数组。reshape不会改变这一点。
即使我们恢复了短数组的长度,我们也不能制作一个2d数组:

In [104]: foobar[3]=np.arange(3)    
In [105]: np.array(foobar)
Out[105]: 
array([array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4]),
       array([0, 1, 2])], dtype=object)

我们必须使用concatenate的某个版本。这里stack工作得很好:

In [106]: np.stack(foobar)
Out[106]: 
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4],
       [0, 1, 2]])

请注意,如果我尝试在[103] foobar上使用stack,它会引发错误。
因此,如果你得到一个1d对象dtype数组,但期望一个2d数值数组,检查元素数组/列表大小。创建不规则对象阵列不再是默认的回退选项。

相关问题