为啥将 np.concatenate 与 for 循环和列表理解一起使用的结果不一样?

Posted

技术标签:

【中文标题】为啥将 np.concatenate 与 for 循环和列表理解一起使用的结果不一样?【英文标题】:Why the result of using np.concatenate with for loop and list comprehension is not the same?为什么将 np.concatenate 与 for 循环和列表理解一起使用的结果不一样? 【发布时间】:2022-01-15 00:21:17 【问题描述】:

我想知道为什么这两段代码的结果不同,想知道如何只使用for循环来达到与列表推导相同的结果:

a = []
c = []

n = np.array([1,2],dtype=np.float32)
m = np.array([1,3],dtype=np.float32)
b = np.array([3], dtype=np.float32)

a.append([n, m, b])
a.append([n, m, b])
a.append([n, m, b])

e = np.array([])
for obs,_,act in a:
    g = [obs,act]
    e = np.concatenate([e,g])
e = np.array([e])

f = np.array( [np.concatenate([obs,act]) for obs,_,act in a ])

print("using for loop:\n", e)
print("using list comprehension:\n", f)

结果是:

using for loop:
 [[array([1., 2.], dtype=float32) array([3.], dtype=float32)
  array([1., 2.], dtype=float32) array([3.], dtype=float32)
  array([1., 2.], dtype=float32) array([3.], dtype=float32)]] 

using list comprehension:
 [[1. 2. 3.]
 [1. 2. 3.]
 [1. 2. 3.]]

为什么?以及如何使 for 循环具有与列表理解相同的结果?

【问题讨论】:

【参考方案1】:

这是因为您没有使用相同操作。试试这样的:

a = []
c = []

n = np.array([1,2],dtype=np.float32)
m = np.array([1,3],dtype=np.float32)
b = np.array([3], dtype=np.float32)

a.append([n, m, b])
a.append([n, m, b])
a.append([n, m, b])

e = []
for obs,_,act in a:
    g = [obs,act]
    e.append(np.concatenate(g))
e = np.array(e)

f = np.array([np.concatenate([obs,act]) for obs,_,act in a ])

print("using for loop:\n", e)
print("using list comprehension:\n", f)
using for loop:
 [[1. 2. 3.]
 [1. 2. 3.]
 [1. 2. 3.]]
using list comprehension:
 [[1. 2. 3.]
 [1. 2. 3.]
 [1. 2. 3.]]

【讨论】:

非常感谢。但似乎很难发现 np.concatenate 也可以制作一个列表元素来做这样的事情而无需任何盲目试验......官方文档没有给我这个方向的提示。【参考方案2】:

你的a

In [238]: a
Out[238]: 
[[array([1., 2.], dtype=float32),
  array([1., 3.], dtype=float32),
  array([3.], dtype=float32)],
 [array([1., 2.], dtype=float32),
  array([1., 3.], dtype=float32),
  array([3.], dtype=float32)],
 [array([1., 2.], dtype=float32),
  array([1., 3.], dtype=float32),
  array([3.], dtype=float32)]]

一个g

In [239]: obs,_,act = a[0]
In [240]: g = [obs,act]
In [241]: g
Out[241]: [array([1., 2.], dtype=float32), array([3.], dtype=float32)]

理解使用:

In [243]: np.concatenate(g)
Out[243]: array([1., 2., 3.], dtype=float32)

迭代(在第一个循环中):

In [247]: e = np.array([])
In [248]: np.concatenate([e,g])
<__array_function__ internals>:5: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
Out[248]: 
array([array([1., 2.], dtype=float32), array([3.], dtype=float32)],
      dtype=object)

这不是加入同样的事情。要获得相同的效果,您需要先将 concatenate 应用于 g 本身:

In [251]: np.concatenate([e,np.concatenate(g)])
Out[251]: array([1., 2., 3.])

也就是说,我们通常不鼓励在循环中使用 e=np.concatenate((e,...))。列表追加速度更快。

【讨论】:

以上是关于为啥将 np.concatenate 与 for 循环和列表理解一起使用的结果不一样?的主要内容,如果未能解决你的问题,请参考以下文章

vstack & hstack & concatenate

如何连接2个数组:1个数组包含字符串,另一个数组包含int64

numpy.array 合并和分割

python 读取csv和excel数据

垂直连接两个NumPy数组

垂直连接两个 NumPy 数组