Python: Differentiating between row and column vectors
Asked Answered
R

13

110

Is there a good way of differentiating between row and column vectors in numpy? If I was to give one a vector, say:

from numpy import *
v = array([1,2,3])

they wouldn't be able to say weather I mean a row or a column vector. Moreover:

>>> array([1,2,3]) == array([1,2,3]).transpose()
array([ True,  True,  True])

Which compares the vectors element-wise.

I realize that most of the functions on vectors from the mentioned modules don't need the differentiation. For example outer(a,b) or a.dot(b) but I'd like to differentiate for my own convenience.

Ruthie answered 2/7, 2013 at 14:44 Comment(4)
The behavior that you are observing is actually correct "in the real world": a one dimensional sequence of numbers is neither a row nor a column vector. A row or column vector is in fact a two dimensional array (in which one of the two dimensions is 1). Thus, your tests should be done with array([[1, 2, 3]]), instead, which is not equal to its transpose.Silhouette
This is actually mathematically not quite right. Matrices are mxn, and row vectors are by definition those where m=1, and column vectors are those where n=1. Dimensionality is different altogether in math, has to do with number of vectors in basis set in a vector space, so realy we shouldn't be talking about dimensionality of a single vector at all. I think that the original poster in talking about the "real world" was talking about the world of linear algebra and mathematics, so was correct. Programmers tend to use the terms wrong.Kinase
@neuronet, this is actually mathematically not quite right. What you are describing is the way things are e.g. in Matlab, and it is an extremely useful convention. The mathematically correct way would be to distinguish between vectors from a given space (per convention represented as columns) and vectors from its dual space (per convention represented as rows).Letendre
Numpy really has a very poor representation of rows, columns and even the z axis vectors. Extremely unintuitive and annoying to use. I hope somebody creates a more intuitive wrapper over numpy.Oxytocin
I
101

You can make the distinction explicit by adding another dimension to the array.

>>> a = np.array([1, 2, 3])
>>> a
array([1, 2, 3])
>>> a.transpose()
array([1, 2, 3])
>>> a.dot(a.transpose())
14

Now force it to be a column vector:

>>> a.shape = (3,1)
>>> a
array([[1],
       [2],
       [3]])
>>> a.transpose()
array([[1, 2, 3]])
>>> a.dot(a.transpose())
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])

Another option is to use np.newaxis when you want to make the distinction:

>>> a = np.array([1, 2, 3])
>>> a
array([1, 2, 3])
>>> a[:, np.newaxis]
array([[1],
       [2],
       [3]])
>>> a[np.newaxis, :]
array([[1, 2, 3]])
Imparadise answered 2/7, 2013 at 14:55 Comment(3)
I thought about that, but it means that getitem becomes inconsistent: a[0] = [1], a[0][0] = 1 for column vector and a[0] = 1, a[0][0] = TypeError for row vector.Ruthie
Yes, that's a trade-off you have to consider. Another option is to use np.newaxis when you need to make the distinction (see edit to my answer).Imparadise
Another way of converting a row vector (1d array) to column vector (returns copy): a.reshape(a.size, 1), or even a.reshape(-1, 1) if u r lazy like meSheri
P
52

Use double [] when writing your vectors.

Then, if you want a row vector:

row_vector = array([[1, 2, 3]])    # shape (1, 3)

Or if you want a column vector:

col_vector = array([[1, 2, 3]]).T  # shape (3, 1)
Pistol answered 26/7, 2017 at 23:46 Comment(0)
P
21

The vector you are creating is neither row nor column. It actually has 1 dimension only. You can verify that by

  • checking the number of dimensions myvector.ndim which is 1
  • checking the myvector.shape, which is (3,) (a tuple with one element only). For a row vector is should be (1, 3), and for a column (3, 1)

Two ways to handle this

  • create an actual row or column vector
  • reshape your current one

You can explicitly create a row or column

row = np.array([    # one row with 3 elements
   [1, 2, 3]
]
column = np.array([  # 3 rows, with 1 element each
    [1],
    [2],
    [3]
])

or, with a shortcut

row = np.r_['r', [1,2,3]]     # shape: (1, 3)
column = np.r_['c', [1,2,3]]  # shape: (3,1)

Alternatively, you can reshape it to (1, n) for row, or (n, 1) for column

row = my_vector.reshape(1, -1)
column = my_vector.reshape(-1, 1)

where the -1 automatically finds the value of n.

Pudendum answered 12/12, 2018 at 14:10 Comment(2)
But if it is neither row and column what is the result of a matrix multiplication? For example A is 2x2 and b is array of length 2. Then A @ b is what ? So we see with that example that b HAS to be a column vector!Staminody
@LorisFoe: b @ A also gives something. by that example, we see that it can't be a column vector. look up broadcastingPudendum
S
8

I think you can use ndmin option of numpy.array. Keeping it to 2 says that it will be a (4,1) and transpose will be (1,4).

>>> a = np.array([12, 3, 4, 5], ndmin=2)
>>> print a.shape
>>> (1,4)
>>> print a.T.shape
>>> (4,1)
Subtraction answered 27/5, 2015 at 5:44 Comment(0)
S
5

You can store the array's elements in a row or column as follows:

>>> a = np.array([1, 2, 3])[:, None] # stores in rows
>>> a
array([[1],
       [2],
       [3]])

>>> b = np.array([1, 2, 3])[None, :] # stores in columns
>>> b
array([[1, 2, 3]])
Sudoriferous answered 20/2, 2019 at 1:44 Comment(0)
S
4

If you want a distiction for this case I would recommend to use a matrix instead, where:

matrix([1,2,3]) == matrix([1,2,3]).transpose()

gives:

matrix([[ True, False, False],
        [False,  True, False],
        [False, False,  True]], dtype=bool)

You can also use a ndarray explicitly adding a second dimension:

array([1,2,3])[None,:]
#array([[1, 2, 3]])

and:

array([1,2,3])[:,None]
#array([[1],
#       [2],
#       [3]])
Sukkoth answered 2/7, 2013 at 15:5 Comment(2)
array([1,2,3])[None,:] is much more complicated than the explicit array([[1, 2, 3]]).Silhouette
matrix is generally worth avoiding, as it doesn't generalize to higher dimensionsMaggot
K
3

If I want a 1x3 array, or 3x1 array:

import numpy as np
row_arr = np.array([1,2,3]).reshape((1,3))
col_arr = np.array([1,2,3]).reshape((3,1)))

Check your work:

row_arr.shape  #returns (1,3)
col_arr.shape  #returns (3,1)

I found a lot of answers here are helpful, but much too complicated for me. In practice I come back to shape and reshape and the code is readable: very simple and explicit.

Kinase answered 18/7, 2019 at 14:2 Comment(0)
H
2

It looks like Python's Numpy doesn't distinguish it unless you use it in context:

"You can have standard vectors or row/column vectors if you like. "

" :) You can treat rank-1 arrays as either row or column vectors. dot(A,v) treats v as a column vector, while dot(v,A) treats v as a row vector. This can save you having to type a lot of transposes. "

Also, specific to your code: "Transpose on a rank-1 array does nothing. " Source: Link

Hepzi answered 2/7, 2013 at 14:53 Comment(1)
I know that. I want a way to differentiate them. Maybe some other math module?Ruthie
S
2

When I tried to compute w^T * x using numpy, it was super confusing for me as well. In fact, I couldn't implement it myself. So, this is one of the few gotchas in NumPy that we need to acquaint ourselves with.

As far as 1D array is concerned, there is no distinction between a row vector and column vector. They are exactly the same.

Look at the following examples, where we get the same result in all cases, which is not true in (the theoretical sense of) linear algebra:

In [37]: w
Out[37]: array([0, 1, 2, 3, 4])

In [38]: x
Out[38]: array([1, 2, 3, 4, 5])

In [39]: np.dot(w, x)
Out[39]: 40

In [40]: np.dot(w.transpose(), x)
Out[40]: 40

In [41]: np.dot(w.transpose(), x.transpose())
Out[41]: 40

In [42]: np.dot(w, x.transpose())
Out[42]: 40

With that information, now let's try to compute the squared length of the vector |w|^2.

For this, we need to transform w to 2D array.

In [51]: wt = w[:, np.newaxis]

In [52]: wt
Out[52]: 
array([[0],
       [1],
       [2],
       [3],
       [4]])

Now, let's compute the squared length (or squared magnitude) of the vector w :

In [53]: np.dot(w, wt)
Out[53]: array([30])

Note that we used w, wt instead of wt, w (like in theoretical linear algebra) because of shape mismatch with the use of np.dot(wt, w). So, we have the squared length of the vector as [30]. Maybe this is one of the ways to distinguish (numpy's interpretation of) row and column vector?

And finally, did I mention that I figured out the way to implement w^T * x ? Yes, I did :

In [58]: wt
Out[58]: 
array([[0],
       [1],
       [2],
       [3],
       [4]])

In [59]: x
Out[59]: array([1, 2, 3, 4, 5])

In [60]: np.dot(x, wt)
Out[60]: array([40])

So, in NumPy, the order of the operands is reversed, as evidenced above, contrary to what we studied in theoretical linear algebra.


P.S. : potential gotchas in numpy

Stylite answered 20/3, 2017 at 15:50 Comment(1)
if you try doing np.hstack or np.vstack on a list of 1-D arrays, it does actually make a difference! If each of the arrays has shape (10, ), the results for hstack is (20,) and for vstack it is (2, 10). This means they are assumed to be column vectors!Plow
E
0

Here's another intuitive way. Suppose we have:

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

First we make a 2D array with that as the only row:

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

Then we can transpose it:

>>> a.T
array([[1],
       [3],
       [4]])
Earlearla answered 21/3, 2017 at 6:33 Comment(0)
D
0

row vectors are (1,0) tensor, vectors are (0, 1) tensor. if using v = np.array([[1,2,3]]), v become (0,2) tensor. Sorry, i am confused.

Denature answered 1/11, 2019 at 5:43 Comment(0)
L
0

From a Matlab background, I like to mentally visualize matrix operations with rows and columns. Should one map inner and outer to the matlab (1xm * mx1) and (mx1 * 1xm)?

>>> b
array([0, 1, 2])
>>> b.transpose()
array([0, 1, 2])
>>> c = outer(b.transpose(), b)
>>> c
array([[0, 0, 0],
       [0, 1, 2],
       [0, 2, 4]])
>>> c = matmul(b.transpose(), b)
>>> c
5
>>> c = matmul(b, b.transpose())
>>> c
5
>>> c = outer(b, b)
>>> c
array([[0, 0, 0],
       [0, 1, 2],
       [0, 2, 4]])
>>> c = inner(b, b)
>>> c
5
>>>
Liripipe answered 20/4 at 4:29 Comment(0)
A
-1

The excellent Pandas library adds features to numpy that make these kinds of operations more intuitive IMO. For example:

import numpy as np
import pandas as pd

# column
df = pd.DataFrame([1,2,3])

# row
df2 = pd.DataFrame([[1,2,3]])

You can even define a DataFrame and make a spreadsheet-like pivot table.

Antitype answered 2/7, 2013 at 15:9 Comment(1)
Since you can write the same thing in NumPy, I would add the important fact that both df[0] = 10 and df2[0] = 10 work as expected when thinking of row and column vectors. This is where Pandas is convenient, compared to NumPy.Silhouette

© 2022 - 2024 — McMap. All rights reserved.