1

I want to append a numpy array(matrix) into an array through a loop

data=[[2 2 2] [3 3 3]]
Weights=[[4 4 4] [4 4 4] [4 4 4]]
All=np.array([])  
for i in data:
    #i=[2 2 2 ]  #for example
    h=i*Weights         
    #h=[[8 8 8][8 8 8][8 8 8]] 
    All=np.concatenate((All,h),axis=0)                

I ge this error:

ValueError: all the input arrays must have same number of dimensions

I want "All" variable to be

[[8 8 8][8 8 8][8 8 8] [12 12 12][12 12 12][12 12 12]]

Any way how I can add "h" to "All" through the loop ?

Psidom
  • 209,562
  • 33
  • 339
  • 356
Adam
  • 159
  • 2
  • 5
  • 12

4 Answers4

2

Option 1: Reshape your initial All array to 3 columns so that the number of columns match h:

All=np.array([]).reshape((0,3))

for i in data:
    h=i*Weights      
    All=np.concatenate((All,h))

All
#array([[  8.,   8.,   8.],
#       [  8.,   8.,   8.],
#       [  8.,   8.,   8.],
#       [ 12.,  12.,  12.],
#       [ 12.,  12.,  12.],
#       [ 12.,  12.,  12.]])

Option 2: Use a if-else statement to handle initial empty array case:

All=np.array([])
for i in data:
    h=i*Weights      
    if len(All) == 0:
        All = h
    else:
        All=np.concatenate((All,h))

All
#array([[ 8,  8,  8],
#       [ 8,  8,  8],
#       [ 8,  8,  8],
#       [12, 12, 12],
#       [12, 12, 12],
#       [12, 12, 12]])

Option 3: Use itertools.product():

import itertools
np.array([i*j for i,j in itertools.product(data, Weights)])

#array([[ 8,  8,  8],
#       [ 8,  8,  8],
#       [ 8,  8,  8],
#       [12, 12, 12],
#       [12, 12, 12],
#       [12, 12, 12]])
Psidom
  • 209,562
  • 33
  • 339
  • 356
  • I tried the second option, it worked fine and made the purpose. – Adam Oct 22 '16 at 01:09
  • I would say I tried the third option, but it didn't really work well for me – Adam Oct 22 '16 at 01:10
  • Interesting. Maybe your data is more complicated than what you've shown, it gives the desired output in both python 2 and python 3 for me. – Psidom Oct 22 '16 at 01:18
  • That is true, my data is more complicated. I tried to simplify it in the question – Adam Oct 22 '16 at 02:25
0

Adam, how about just using a pair of nested loops? I believe this code will do what you want.

import numpy as np
data = ([2,2,2],[3,3,3])
weights = ([4,4,4],[4,4,4],[4,4,4])

output=np.array([])
for each_array in data:
    for weight in weights:
            each_multiplication = np.multiply(each_array, weight)
            output = np.append(output,each_multiplication)

print output

np.multiply() performs element wise multiplication instead of matrix multiplication. As best as I can understand from your sample input and output, this is what you're trying to accomplish.

Cinghiale
  • 164
  • 1
  • 5
0

It may not be the best solution but it seems to work.

data = np.array([[2, 2, 2], [3, 3, 3]])
Weights = np.array([[4, 4, 4], [4, 4, 4], [4, 4, 4]])
All = []

for i in data:
    for j in Weights:
        h = i * j
        All.append(h)

All = np.array(All)

I'd like to say it's not the best solution because it appends the result to a list and at the end converts the list in a numpy array but it works good for small applications. I mean if you have to do heavy calculations like this it's i would consider finding another method. Anyway with this method you don't have to think about the number conversions from floating point. Hope this helps.

Nensi601
  • 116
  • 6
  • This is a widely used way of constructing an array when looping is necessary. – hpaulj Oct 22 '16 at 01:06
  • yeah i agree. i mean if you have to use this just for some small calculations i think it can do well, but it is slower than just using numpy and for sure appending to an array to every iteration is something to avoid if the array is long. – Nensi601 Oct 22 '16 at 01:12
0

A preferred way of constructing an array with a loop is to collect values in a list, and perform the concatenate once, at the end:

In [1025]: data
Out[1025]: 
array([[2, 2, 2],
       [3, 3, 3]])
In [1026]: Weights
Out[1026]: 
array([[4, 4, 4],
       [4, 4, 4],
       [4, 4, 4]])

Append to a list is much faster than repeated concatenate; plus it avoids the 'empty` array shape issue:

In [1027]: alist=[]
In [1028]: for row in data:
      ...:     alist.append(row*Weights)
In [1029]: alist
Out[1029]: 
[array([[8, 8, 8],
        [8, 8, 8],
        [8, 8, 8]]), array([[12, 12, 12],
        [12, 12, 12],
        [12, 12, 12]])]

In [1031]: np.concatenate(alist,axis=0)
Out[1031]: 
array([[ 8,  8,  8],
       [ 8,  8,  8],
       [ 8,  8,  8],
       [12, 12, 12],
       [12, 12, 12],
       [12, 12, 12]])

You can also join the arrays on a new dimension with np.array or np.stack:

In [1032]: np.array(alist)
Out[1032]: 
array([[[ 8,  8,  8],
        [ 8,  8,  8],
        [ 8,  8,  8]],

       [[12, 12, 12],
        [12, 12, 12],
        [12, 12, 12]]])
In [1033]: _.shape
Out[1033]: (2, 3, 3)

I can construct this 3d version with a simple broadcasted multiplication - no loops

In [1034]: data[:,None,:]*Weights[None,:,:]
Out[1034]: 
array([[[ 8,  8,  8],
        [ 8,  8,  8],
        [ 8,  8,  8]],

       [[12, 12, 12],
        [12, 12, 12],
        [12, 12, 12]]])

Add a .reshape(-1,3) to that to get the (6,3) version.

np.repeat(data,3,axis=0)*np.tile(Weights,[2,1]) also produces the desired 6x3 array.

hpaulj
  • 221,503
  • 14
  • 230
  • 353