################### NumPy ###################
>>> import numpy as np
>>> a = np.array([1, 2, 3, 4])
>>> a
array([1, 2, 3, 4])
>>> a.T
array([1, 2, 3, 4])
>>> a.shape
(4,)
>>> a.ndim
1
>>> b = np.arange(8).reshape(4, 2)
>>> b
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> np.column_stack((a, b))
array([[1, 0, 1],
       [2, 2, 3],
       [3, 4, 5],
       [4, 6, 7]])
>>> a * a
array([ 1,  4,  9, 16])
>>> a.dot(a)
30
>>> a.dot(a.T)
30
>>> from numpy import newaxis
>>> a
array([1, 2, 3, 4])
>>> a[:,newaxis]
array([[1],
       [2],
       [3],
       [4]])
>>> a[newaxis,:]
array([[1, 2, 3, 4]])
>>> a[:,newaxis].shape
(4, 1)
>>> a[newaxis,:].shape
(1, 4)
>>> a.reshape(4,1)
array([[1],
       [2],
       [3],
       [4]])
>>> a.reshape(1,4)
array([[1, 2, 3, 4]])
>>> a.reshape(4,1).dot(a.reshape(1,4))
array([[ 1,  2,  3,  4],
       [ 2,  4,  6,  8],
       [ 3,  6,  9, 12],
       [ 4,  8, 12, 16]])
>>> np.outer(a, a)
array([[ 1,  2,  3,  4],
       [ 2,  4,  6,  8],
       [ 3,  6,  9, 12],
       [ 4,  8, 12, 16]])
>>> b
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> b.ravel()
array([0, 1, 2, 3, 4, 5, 6, 7])
>>> b.ravel(order='C')
array([0, 1, 2, 3, 4, 5, 6, 7])
>>> b.ravel(order='F')
array([0, 2, 4, 6, 1, 3, 5, 7])
>>> a
array([1, 2, 3, 4])
>>> a.reshape(2, 2)
array([[1, 2],
       [3, 4]])
>>> a.reshape(-1, 2)
array([[1, 2],
       [3, 4]])
>>> a * b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4,) (4,2) 
>>> a.reshape(4, 1) * b
array([[ 0,  1],
       [ 4,  6],
       [12, 15],
       [24, 28]])
>>> np.zeros(4)
array([ 0.,  0.,  0.,  0.])
>>> np.zeros(b.shape, dtype=int)
array([[0, 0],
       [0, 0],
       [0, 0],
       [0, 0]])
>>> np.zeros_like(b)
array([[0, 0],
       [0, 0],
       [0, 0],
       [0, 0]])
>>> np.eye(3)
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> np.eye(3) + 1
array([[ 2.,  1.,  1.],
       [ 1.,  2.,  1.],
       [ 1.,  1.,  2.]])
>>> np.eye(3) + np.arange(3)
array([[ 1.,  1.,  2.],
       [ 0.,  2.,  2.],
       [ 0.,  1.,  3.]])
>>> np.eye(3) + np.arange(3).T
array([[ 1.,  1.,  2.],
       [ 0.,  2.,  2.],
       [ 0.,  1.,  3.]])
>>> np.eye(3) + np.arange(3)[:,newaxis]
array([[ 1.,  0.,  0.],
       [ 1.,  2.,  1.],
       [ 2.,  2.,  3.]])
>>> a.max()
4
>>> b.max()
7
>>> b
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> b.max(axis=0)
array([6, 7])
>>> b.max(axis=1)
array([1, 3, 5, 7])
>>> np.maximum(a, b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4,) (4,2) 
>>> np.maximum(a[:, newaxis], b)
array([[1, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> np.maximum(a[:2], b)
array([[1, 2],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> b
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> b.sum()
28
>>> b.sum(axis=0)
array([12, 16])
>>> b.sum(axis=1)
array([ 1,  5,  9, 13])
>>> b.sum(axis=1).shape
(4,)
>>> b.sum(axis=(0,1))
28
>>> b.mean(axis=0)
array([ 3.,  4.])
>>> b.std(axis=0)
array([ 2.23606798,  2.23606798])
>>> np.stack((a, a))
array([[1, 2, 3, 4],
       [1, 2, 3, 4]])
>>> np.stack((a, a), axis = -1)
array([[1, 1],
       [2, 2],
       [3, 3],
       [4, 4]])
>>> np.stack((a, a), axis = 1)
array([[1, 1],
       [2, 2],
       [3, 3],
       [4, 4]])
>>> np.split(b, 2)
[array([[0, 1],
       [2, 3]]), array([[4, 5],
       [6, 7]])]
>>> np.split(b, 2, axis=1)
[array([[0],
       [2],
       [4],
       [6]]), array([[1],
       [3],
       [5],
       [7]])]
>>> b
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> a
array([1, 2, 3, 4])
>>> b.T.dot(a)
array([40, 50])
>>> np.vdot(a, b[:2])
20

################## SciPy ###################
>>> from numpy import linalg as la
>>> a
array([1, 2, 3, 4])
>>> la.norm(a)
5.4772255750516612
>>> b
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])
>>> la.norm(b)
11.832159566199232
>>> la.norm(b, axis=0)
array([ 7.48331477,  9.16515139])
>>> la.norm(b, axis=1)
array([ 1.        ,  3.60555128,  6.40312424,  9.21954446])
>>> np.outer(a, a)
array([[ 1,  2,  3,  4],
       [ 2,  4,  6,  8],
       [ 3,  6,  9, 12],
       [ 4,  8, 12, 16]])
>>> la.matrix_rank(np.outer(a,a))
1
>>> c = np.random.randint(0, 10, (4, 4))
>>> c
array([[0, 3, 4, 7],
       [5, 7, 4, 5],
       [5, 6, 4, 9],
       [4, 3, 0, 8]])
>>> la.matrix_rank(c)
4
>>> la.eig(np.eye(4))
(array([ 1.,  1.,  1.,  1.]), array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]]))
>>> la.eig(np.outer(a,a))
(array([  0.00000000e+00,   3.00000000e+01,   3.94430453e-31,
         1.24037229e-15]), array([[-0.98319208,  0.18257419,  0.38619162,  0.11952286],
       [ 0.06780635,  0.36514837, -0.56506661,  0.23904572],
       [ 0.10170953,  0.54772256, -0.48171509, -0.83666003],
       [ 0.1356127 ,  0.73029674,  0.54727172,  0.47809144]]))
>>> c = np.random.randint(0, 10, (4, 4))
>>> c
array([[0, 3, 4, 7],
       [5, 7, 4, 5],
       [5, 6, 4, 9],
       [4, 3, 0, 8]])
>>> la.matrix_rank(c)
4
>>> np.trace(c)
19
>>> qr = la.qr(c)
>>> qr
(array([[ 0.        ,  0.82676738, -0.05225137,  0.56011203],
       [-0.61545745,  0.32152065,  0.58426536, -0.42008403],
       [-0.61545745,  0.04593152, -0.77427035, -0.14002801],
       [-0.49236596, -0.45931521,  0.23750624,  0.70014004]]),
array([[ -8.1240384 ,  -9.47804481,  -4.92365964, -12.55533208],
       [  0.        ,   3.62859018,   4.77687821,   4.13383691],
       [  0.        ,   0.        ,  -0.96902547,  -2.51281604],
       [  0.        ,   0.        ,   0.        ,   6.16123237]]))
>>> la.det(qr[0])
-0.99999999999999944
>>> qr[0].T.dot(qr[0])
array([[  1.00000000e+00,   1.94289029e-16,   0.00000000e+00,
          1.11022302e-16],
       [  1.94289029e-16,   1.00000000e+00,   0.00000000e+00,
         -2.22044605e-16],
       [  0.00000000e+00,   0.00000000e+00,   1.00000000e+00,
         -5.55111512e-17],
       [  1.11022302e-16,  -2.22044605e-16,  -5.55111512e-17,
          1.00000000e+00]])
>>> np.round(qr[0].T.dot(qr[0]))
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0., -0.],
       [ 0.,  0.,  1., -0.],
       [ 0., -0., -0.,  1.]])
