Home > Software design >  Why the result of using np.concatenate with for loop and list comprehension is not the same?
Why the result of using np.concatenate with for loop and list comprehension is not the same?

Time:12-11

I am wondering why the results of these two pieces of code are different,and want to know how to use only for loop to achieve the same result as list comprehension:

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)

The result is:

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.]]

why?and how to make the for loop to have the same result as list comprehension?

CodePudding user response:

It is because you are not using the same operation. Try this:

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.]]

CodePudding user response:

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

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

The comprehension uses:

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

The iteration does (in the first loop):

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)

That's not joining the same things. To get the same thing, you need to first apply concatenate to g itself:

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

That said, we generally discourage using e=np.concatenate((e,...)) in a loop. List append is faster.

  • Related