3

I do not understand what happens when multiplying Numpy.arrays.

For example, with with jagged (or ragged) arrays

import numpy as np
a = np.array([[1,2,3],[100,200]])
b = np.array([2, 4])
print(a * b)

I get

[[1, 2, 3, 1, 2, 3] [100, 200, 100, 200, 100, 200, 100, 200]]

But, if I modify a little

import numpy as np
a = np.array([[1,2],[100,200]])
b = np.array([2, 4])
print(a * b)

I get

[[  2   8]
[200 800]]

I want to find the definition of array multiplication.

StefanS
  • 1,740
  • 14
  • 20
tiankonghewo
  • 133
  • 7

4 Answers4

3

Your main problem is that your array a isn't a "normal" array, because the second dimensions are not equal. If you try a.shape you get (2,), a.dtype gives dtype('O') (meaning object), and a[0].dtype leads to the attribute error 'list' object has no attribute 'dtype'. This means that you have a numpy array of dimension 2, each containing a python list.

You should look up broadcasting, but it's not the root cause here. It's usually intended to expand dimensions of size 1 to larger values if the arrays don't match during operations. There's a lot more to it, but the documentation is pretty clear. For your specific problem it suffices to say that broadcasting means numpy does not throw an error if the dimensions of two arrays match or one of them is 1 (counting from back to front, filling empty values with 1).

You have two (2,) arrays (a containing 2 lists, b containing 2 integers), which means that the dimensions fit (no broadcasting necessary).

The rest of this "misbehavior" (it isn't) has nothing to do with numpy, because in standard python (which comes into play because a contains python lists) multiplying a list with a scalar duplicates and appends the list that often.

So

>>>[1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

and the same thing happens in your case: the first list in a gets multiplied by 2 and the second list by 4.

StefanS
  • 1,740
  • 14
  • 20
0

I think its "replicating ('a' array column [x]) ('b' array index [x])times". If your objective is doing multiplication, use NP.dot instead

duck
  • 369
  • 3
  • 17
  • After I had written my answer I finally understood yours. You managed to express it much more succinctly. However, `np.dot` does not work much better, because the underlying problem of an array containing lists still exists. – StefanS Nov 08 '16 at 08:34
  • 1
    You can go to http://stackoverflow.com/questions/3890621/how-does-multiplication-differ-for-numpy-matrix-vs-array-classes there are wonderful explanation which i think you will be interested – duck Nov 08 '16 at 08:38
  • Your are right, there are a lot of good answers behind that link. However, non of them are pertinent to this question here, where the problem isn't really the multiplication but the (very non-standard) jagged array. – StefanS Nov 08 '16 at 08:52
  • `np.tensordot` has an example of string replication. – hpaulj Nov 08 '16 at 12:38
0

An example in the np.tensordot docs might help. It creates a object array of strings, and shows that dot produces string replication.

For strings and list * means replication

In [134]: 'abc'*3
Out[134]: 'abcabcabc'

Your arrays:

In [126]: a
Out[126]: array([[1, 2, 3], [100, 200]], dtype=object)
In [127]: b
Out[127]: array([2, 4])

and a string array (I could have also done a[:]=['a','B'])

In [128]: c = np.array(['a','B'],dtype=object)
In [129]: c
Out[129]: array(['a', 'B'], dtype=object)

element multiplication - replicate the elements of a 2 and 3 times.

In [130]: a*b
Out[130]: array([[1, 2, 3, 1, 2, 3], [100, 200, 100, 200, 100, 200, 100, 200]], dtype=object)

dot product - same thing, but it 'sums' the values after * - and sum for list is concatenation.

In [131]: a.dot(b)
Out[131]: [1, 2, 3, 1, 2, 3, 100, 200, 100, 200, 100, 200, 100, 200]

Same thing happens with the array of characters, replication and concatenation.

In [132]: c*b
Out[132]: array(['aa', 'BBBB'], dtype=object)
In [133]: c.dot(b)
Out[133]: 'aaBBBB'

When dealing with an object dtype array, numpy essentially iterates over the elements and applies the operator/method defined the class of that object.

a*b is in effect

In [147]: [i*j for i,j in zip(a,b)]
Out[147]: [[1, 2, 3, 1, 2, 3], [100, 200, 100, 200, 100, 200, 100, 200]]

The numpy version is a little fancier in that can handle multidimensional arrays and use broadcasting.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
-1

Basically the numpy array a*b returns elementary multiplication and the multiplication should work like this.

Eg-1

import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print(a * b)

Output:

[[ 5 12] [21 32]]

Eg-2

import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([5,6])
print(a * b)

Output:

[[ 5 12] [15 24]]
aavrug
  • 1,849
  • 1
  • 12
  • 20