Introduction
Strictly speaking, there is no notion of 1D array in MATLAB programming: although row vector and column vector look like 1D arrays, in fact they are viewed as 2D arrays, just like a vector can be regarded as a special 2D matrix from the perspective of mathematics. As for why MATLAB designed like this, I think it’s probably determined by its product positioning, that is providing convenience for mathematical computations, and hence defining 1D array is not necessary.
As for other programming languages, some of them choose to differentiate 1D and 2D array, such as Python and C. Array is a common data structure, and although it usually be seen as the counterpart of vector in mathematics, but array is more ‘practical’: its implementation involves operations on computer memory. Therefore, although I don’t get into the specific array construction mechanism, I guess that 1D array has its special advantages (may from the both perspectives of computation time and storage space) compared with 2D row vector and column vector.
So, it’s better to treat array (a data structure in programming) and vector (in mathematics) as two standalone notions, accepting that a 1D array is just a sequence of numbers, neither a row nor a column vector. However, due to that I was used to MATLAB programming syntax before, I’m still not that familiar with 1D array and its difference between row vector and column vector when I turn to Python. Therefore, I’ll take some notes about them in this post by taking NumPy array and PyTorch tensor as examples.
Define 1D array, column and row vector, and transpose them
NumPy array
Take Python NumPy package. Methods to create 1D array and column and row vector (2D array) show as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| import numpy as np
# 1D array
a = np.array([1.0, 2.0, 3.0])
print('# 1D array')
print(a, a.shape, '\n')
# Row vector (2D array)
b = np.array([[1.0, 2.0, 3.0]])
print('# Row vector (2D array)')
print(b, b.shape, '\n')
# Column vector (2D array)
c = np.array([[1.0], [2.0], [3.0]])
print('# Column vector (2D array)')
print(c, c.shape, '\n')
|
1
2
3
4
5
6
7
8
9
10
| # 1D array
[1. 2. 3.] (3,)
# Row vector (2D array)
[[1. 2. 3.]] (1, 3)
# Column vector (2D array)
[[1.]
[2.]
[3.]] (3, 1)
|
It should be noted that the shape of 1D array is (3,)
, which looks very different from row and column vector.
For 1D array, its transpose is itself; for row vector (2D array), its transpose is column vector, and vice versa. By the way, there are two ways to make transpose.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # For 1D array
aT1 = a.transpose()
aT2 = a.T
print('# For 1D array')
print(aT1, aT1.shape)
print(aT2, aT2.shape, '\n')
# For row vector (2D array)
bT1 = b.transpose()
bT2 = b.T
print('# For row vector (2D array)')
print(bT1, bT1.shape)
print(bT2, bT2.shape, '\n')
# For column vector (2D array)
cT1 = c.transpose()
cT2 = c.T
print('# For column vector (2D array)')
print(cT1, cT1.shape)
print(cT2, cT2.shape, '\n')
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # For 1D array
[1. 2. 3.] (3,)
[1. 2. 3.] (3,)
# For row vector (2D array)
[[1.]
[2.]
[3.]] (3, 1)
[[1.]
[2.]
[3.]] (3, 1)
# For column vector (2D array)
[[1. 2. 3.]] (1, 3)
[[1. 2. 3.]] (1, 3)
|
PyTorch tensor
For PyTorch tensor, the situation is basically the same:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| import torch
# 1D tensor
a = torch.tensor([1.0, 2.0, 3.0])
print('# 1D tensor')
print(a, a.shape, '\n')
# Row vector (2D tensor)
b = torch.tensor([[1.0, 2.0, 3.0]])
print('# Row vector (2D tensor)')
print(b, b.shape, '\n')
# Column vector (2D tensor)
c = torch.tensor([[1.0], [2.0], [3.0]])
print('# Column vector (2D tensor)')
print(c, c.shape, '\n')
|
1
2
3
4
5
6
7
8
9
10
| # 1D tensor
tensor([1., 2., 3.]) torch.Size([3])
# Row vector (2D tensor)
tensor([[1., 2., 3.]]) torch.Size([1, 3])
# Column vector (2D tensor)
tensor([[1.],
[2.],
[3.]]) torch.Size([3, 1])
|
Similarly, row vector and column vector, i.e. 2D tensor, are transposes of each other:
1
2
3
4
5
6
7
8
9
10
11
12
13
| # For row vector (2D tensor)
bT1 = b.transpose(1,0)
bT2 = b.T
print('# For row vector (2D tensor)')
print(bT1, bT1.shape)
print(bT2, bT2.shape, '\n')
# For column vector (2D tensor)
cT1 = c.transpose(1,0)
cT2 = c.T
print('# For column vector (2D tensor)')
print(cT1, cT1.shape)
print(cT2, cT2.shape, '\n')
|
1
2
3
4
5
6
7
8
9
10
11
| # For row vector (2D tensor)
tensor([[1.],
[2.],
[3.]]) torch.Size([3, 1])
tensor([[1.],
[2.],
[3.]]) torch.Size([3, 1])
# For column vector (2D tensor)
tensor([[1., 2., 3.]]) torch.Size([1, 3])
tensor([[1., 2., 3.]]) torch.Size([1, 3])
|
but 1D tensor doesn’t support transpose operation:
1
2
3
4
5
6
| # For 1D array
aT1 = a.T
aT2 = a.transpose()
print('# For 1D tensor')
print(aT1, aT1.shape)
print(aT2, aT2.shape, '\n')
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| C:\Users\whatastarrynight\AppData\Local\Temp\ipykernel_20108\2759700227.py:2: UserWarning: The use of `x.T` on tensors of dimension other than 2 to reverse their shape is deprecated and it will throw an error in a future release. Consider `x.mT` to transpose batches of matrices or `x.permute(*torch.arange(x.ndim - 1, -1, -1))` to reverse the dimensions of a tensor. (Triggered internally at ..\aten\src\ATen\native\TensorShape.cpp:3679.)
aT1 = a.T
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[61], line 3
1 # For 1D array
2 aT1 = a.T
----> 3 aT2 = a.transpose()
4 print('# For 1D tensor')
5 print(aT1, aT1.shape)
TypeError: transpose() received an invalid combination of arguments - got (), but expected one of:
* (int dim0, int dim1)
* (name dim0, name dim1)
|
Convert a 1D array into a 2D array (row vector or column vector)
NumPy array
(1) By np.newaxis
1
2
3
4
5
6
7
8
9
10
11
12
| import numpy as np
# 1D array
a = np.array([1.0, 2.0, 3.0])
# Convert 1D array to 2D row vector
a2 = a[np.newaxis, :]
print(a2, a2.shape)
# Convert 1D array to 2D column vector
a3 = a[:, np.newaxis]
print(a3, a3.shape)
|
1
2
3
4
| [[1. 2. 3.]] (1, 3)
[[1.]
[2.]
[3.]] (3, 1)
|
(2) By np.expand_dims
1
2
3
4
5
6
7
| # Convert 1D array to 2D row vector
a4 = np.expand_dims(a, axis=0)
print(a4, a4.shape)
# Convert 1D array to 2D column vector
a5 = np.expand_dims(a, axis=1)
print(a5, a5.shape)
|
1
2
3
4
| [[1. 2. 3.]] (1, 3)
[[1.]
[2.]
[3.]] (3, 1)
|
(3) By reshape
method
1
2
3
4
5
6
7
| # Convert 1D array to 2D row vector
a6 = a.reshape(1,-1)
print(a6, a6.shape)
# Convert 1D array to 2D column vector
a7 = a.reshape(-1,1)
print(a7, a7.shape)
|
1
2
3
4
| [[1. 2. 3.]] (1, 3)
[[1.]
[2.]
[3.]] (3, 1)
|
PyTorch tensor
(1) By np.newaxis
1
2
3
4
5
6
7
8
9
10
11
12
13
| import torch
import numpy as np
# 1D tensor
a = torch.tensor([1.0, 2.0, 3.0])
# Convert 1D tensor to 2D row tensor
a1 = a[np.newaxis, :]
print(a1, a1.shape)
# Convert 1D tensor to 2D column tensor
a2 = a[:, np.newaxis]
print(a2, a2.shape)
|
1
2
3
4
| tensor([[1., 2., 3.]]) torch.Size([1, 3])
tensor([[1.],
[2.],
[3.]]) torch.Size([3, 1])
|
(2) By reshape
method
1
2
3
4
5
6
7
| # Convert 1D tensor to 2D row vector
a3 = a.reshape(1,-1)
print(a3, a3.shape)
# Convert 1D tensor to 2D column vector
a4 = a.reshape(-1,1)
print(a4, a4.shape)
|
1
2
3
4
| tensor([[1., 2., 3.]]) torch.Size([1, 3])
tensor([[1.],
[2.],
[3.]]) torch.Size([3, 1])
|
References