3

My question is about Python array shape.

What is the difference between array size (2, ) and (2, 1)?

I tried to add those two arrays together. However, I got an error as follows:

Non-broadcastable output operant with shape (2, ) doesn't match the broadcast shape (2, 2)

3
  • Are you trying to add the values of the arrays or add the array [2] to the array of [2, 2] Commented May 24, 2018 at 0:47
  • @Shadmoth the OP is almost certainly referring to the shape attribute of numpy arrays Commented May 24, 2018 at 0:50
  • @yx131, the 1st one is 1 item tuple and the 2nd one is 2 item tuple. In case of numpy arrays, (2,) denotes shape of 1 dimensional array of 2 items and (2, 2) denotes the shape of 2 dimensional array (matrix) with 2 rows and 2 colums. If you want to add 2 arrays then either their shape should be same or they should follow the broadcasting rule of numpy. Commented May 24, 2018 at 2:58

4 Answers 4

2

There is no difference in the raw memory. But logically, one is a one-dimensional array of two values, the other is a 2D array (where one of the dimensions just happens to be size 1).

The logical distinction is important to numpy; when you try to add them, it wants to make a new 2x2 array where the top row is the sum of the (2, 1) array's top "row" with each value in the (2,) array. If you use += to do that though, you're indicating that you expect to be able to modify the (2,) array in place, which is not possible without resizing (which numpy won't do). If you change your code from:

arr1 += arr2

to:

arr1 = arr1 + arr2

it will happily create a new (2, 2) array. Or if the goal was that the 2x1 array should act like a flat 1D array, you can flatten it:

alreadyflatarray += twodarray.flatten()
Sign up to request clarification or add additional context in comments.

Comments

0

(2,) is an unidimensional array, (2,1) is a matrix with only one column

You can easily see the difference by crating arrays full of zeros using np.zero passing the desired shape:

>>> np.zeros((2,))
array([0., 0.])

>>> np.zeros((2,1))
array([[0.],
       [0.]])

Comments

0

@yx131, you can have a look at the below code to just have a clear picture about tuples and it's use in defining the shape of numpy arrays.

Note: Do not forget to see the code below as it has explanation of the problems related to Broadcasting in numpy.

Also check numpy's broadcasting rule at https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html.

There's a difference between (2) and (2,). The first one is a literal value 2 where as the 2nd one is a tuple.

(2,) is 1 item tuple and (2, 2) is 2 items tuple. It is clear in the code example.

Note: In case of numpy arrays, (2,) denotes shape of 1 dimensional array of 2 items and (2, 2) denotes the shape of 2 dimensional array (matrix) with 2 rows and 2 colums. If you want to add 2 arrays then their shape should be same.

v = (2)   # Assignment of value 2
t = (2,)  # Comma is necessary at the end of item to define 1 item tuple, it is not required in case of list
t2 = (2, 1)  # 2 item tuple
t3 = (3, 4)  # 2 item tuple

print(v, type(v))
print(t, type(t))
print(t2, type(t2))
print(t3, type(t3))

print(t + t2)
print(t2 + t3)

"""
2 <class 'int'>
(2,) <class 'tuple'>
(2, 1) <class 'tuple'>
(3, 4) <class 'tuple'>
(2, 2, 1)
(2, 1, 3, 4)
"""

Now, let's have a look at the below code to figure out the error related to broadcasting. It's all related to dimensions.

# Python 3.5.2

import numpy as np

arr1 = np.array([1, 4]);
arr2 = np.array([7, 6, 3, 8]);
arr3 = np.array([3, 6, 2, 1]);

print(arr1, ':', arr1.shape)
print(arr2, ":", arr2.shape)
print(arr3, ":", arr3.shape)
print ("\n")
"""
[1 4] : (2,)
[7 6 3 8] : (4,)
[3 6 2 1] : (4,)
"""

# Changing shapes (dimensions)
arr1.shape = (2, 1)
arr2.shape = (2, 2)
arr3.shape = (2, 2)

print(arr1, ':', arr1.shape)
print(arr2, ":", arr2.shape)
print(arr3, ":", arr3.shape)
print("\n")
print(arr1 + arr2)
"""
[[1]
 [4]] : (2, 1)
[[7 6]
[3 8]] : (2, 2)
[[3 6]
 [2 1]] : (2, 2)


[[ 8  7]
 [ 7 12]]
"""

arr1.shape = (2, )
print(arr1, arr1.shape)
print(arr1 + arr2)
"""
[1 4] (2,)
[[ 8 10]
 [ 4 12]]
"""

# Code with error(Broadcasting related)
arr2.shape = (4,)
print(arr1+arr2)
"""
Traceback (most recent call last):
  File "source_file.py", line 53, in <module>
    print(arr1+arr2)
ValueError: operands could not be broadcast together 
with shapes (2,) (4,) 
"""

So in your case, the problem is related to the mismatched dimensions (acc. to numpy's broadcasting ) to be added. Thanks.

Comments

0

Make an array that has shape (2,)

In [164]: a = np.array([3,6])
In [165]: a
Out[165]: array([3, 6])        
In [166]: a.shape
Out[166]: (2,)
In [167]: a.reshape(2,1)
Out[167]: 
array([[3],
       [6]])
In [168]: a.reshape(1,2)
Out[168]: array([[3, 6]])

The first displays like a simple list [3,6]. The second as a list with 2 nested lists. The third as a list with one nested list of 2 items. So there is a consistent relation between shape and list nesting.

In [169]: a + a
Out[169]: array([ 6, 12])                # shape (2,)
In [170]: a + a.reshape(1,2)
Out[170]: array([[ 6, 12]])             # shape (1,2)
In [171]: a + a.reshape(2,1)
Out[171]: 
array([[ 6,  9],                        # shape (2,2)
       [ 9, 12]])

Dimensions behave as:

(2,) + (2,) => (2,) (2,) + (1,2) => (1,2) + (1,2) => (1,2) (2,) + (2,1) => (1,2) + (2,1) => (2,2) + (2,2) => (2,2)

That is a lower dimensional array can be expanded to the matching number of dimensions with the addition of leading size 1 dimensions.

And size 1 dimensions can be changed to match the corresponding dimension.

I suspect you got the error when doing a a += ... (If so you should have stated that clearly.)

In [172]: a += a
In [173]: a += a.reshape(1,2)
....
ValueError: non-broadcastable output operand with shape (2,) 
    doesn't match the broadcast shape (1,2)

In [175]: a += a.reshape(2,1)
...
ValueError: non-broadcastable output operand with shape (2,) 
    doesn't match the broadcast shape (2,2)

With the a+=... addition, the result shape is fixed at (2,), the shape of a. But as noted above the two additions generate (1,2) and (2,2) results, which aren't compatible with (2,).

The same reasoning can explain these additions and errors:

In [176]: a1 = a.reshape(1,2)
In [177]: a1 += a                
In [178]: a1
Out[178]: array([[12, 24]])
In [179]: a2 = a.reshape(2,1)
In [180]: a2 += a
...
ValueError: non-broadcastable output operand with shape (2,1) 
    doesn't match the broadcast shape (2,2)
In [182]: a1 += a2
...
ValueError: non-broadcastable output operand with shape (1,2) 
    doesn't match the broadcast shape (2,2)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.