user2262504
user2262504

Reputation: 7317

generalisation between vector and matrix, matrix and tensor with numpy ndarray

I found an interesting thing when comparing MATLAB and numpy.

MATLAB:
x = [1, 2]
n = size(X, 2) 
% n = 1

Python:
x = np.array([1, 2])
n = x.shape[1]
# error 

The question is: how to handle input which may be both ndarray with shape (n,) and ndarray with shape (n, m).

e.g.

def my_summation(X):
    """
    X : ndarray
        each column of X is an observation.
    """
    # my solution for ndarray shape (n,)
    # if X.ndim == 1:
    #     X = X.reshape((-1, 1))

    num_of_sample = X.shape[1]
    sum = np.zeros(X.shape[0])
    for i in range(num_of_sample):
        sum = sum + X[:, i]

    return sum


a = np.array([[1, 2], [3, 4]])
b = np.array([1, 2])

print my_summation(a)
print my_summation(b)

My solution is forcing ndarray shape (n,) to be shape (n, 1).

The summation is used as an example. What I want is to find an elegant way to handle the possibility of matrix with only one observation(vector) and matrix with more than one observation using ndarray.

Does anyone have better solutions?

Upvotes: 0

Views: 262

Answers (2)

Divakar
Divakar

Reputation: 221664

In a ndarray X, len(X) would the number of elements along the first axis. So, for a 2D array, it would be the number of rows and for a 1D array, it would be the number of elements in itself. This property could be used to reshape the input array that could be a 1D or a 2D array into a 2D array output. For a 1D array as input, the output 2D array would have number of rows same as number of elements. For a 2D array input case, it would have the number of rows same as before, therefore no change with it.

To sum up, one solution would be to put a reshaping code at the top of the function definition, like so -

X = X.reshape(len(X),-1)

Sample runs -

2D Case:

In [50]: X
Out[50]: 
array([[6, 7, 8, 1],
       [6, 2, 3, 0],
       [5, 1, 8, 6]])

In [51]: X.reshape(len(X),-1)
Out[51]: 
array([[6, 7, 8, 1],
       [6, 2, 3, 0],
       [5, 1, 8, 6]])

1D Case:

In [53]: X
Out[53]: array([2, 5, 2])

In [54]: X.reshape(len(X),-1)
Out[54]: 
array([[2],
       [5],
       [2]])

Upvotes: 1

Rory Yorke
Rory Yorke

Reputation: 2236

I recently learned about numpy.atleast_2d from the Python control toolbox. You also don't need a for-loop for summation, rather use numpy.sum.

import numpy as np


def my_summation(X):
    """
    X : ndarray
        each column of X is an observation.
    """
    # my solution for ndarray shape (n,)
    # if X.ndim == 1:
    #     X = X.reshape((-1, 1))
    X = np.atleast_2d(X)
    return np.sum(X, axis=1)


a = np.array([[1, 2], [3, 4]])
b = np.array([1, 2])

print my_summation(a)
print my_summation(b)

gives

[3 7]
[3]

Upvotes: 1

Related Questions