Почему результат использования np.concatenate с пониманием цикла for и списка не совпадает?

#python #arrays #numpy #concatenation #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)  

В результате получается:

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

Комментарии:

1. Большое спасибо. Но кажется очень трудным выяснить, что np.concatenate также может создать элемент списка, чтобы сделать что-то подобное без каких-либо слепых испытаний…официальный документ не дает мне подсказки в этом направлении tbh.

Ответ №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]) lt;__array_function__ internalsgt;: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)  

Это не одно и то же. Чтобы получить то же самое, вам нужно сначала применить конкатенацию к g себе:

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

Тем не менее, мы обычно не рекомендуем использовать e=np.concatenate((e,...)) его в цикле. Добавление списка происходит быстрее.