VBAユーザがPython・Rを使ってみた：行列

# はじめに

機械学習の勉強を始めたVBAユーザです。
備忘録としてPython・Rの文法をVBAと比較しながらまとめていきたいと思います。


**目次**

- [行列](#行列)
  - [行列の作成](#行列の作成)
     - [mxn行列](#mxn行列)
     - [単位行列](#単位行列)
     - [ゼロ行列](#ゼロ行列)
     - [対角行列](#対角行列)
     - [その他](#その他)
  - [行列の属性](#行列の属性)
  - [行列の要素の取得](#行列の要素の取得)
  - [行列の計算](#行列の計算)
     - [線形代数の計算](#線形代数の計算)
     - [要素ごとの演算](#要素ごとの演算)
- [まとめ](#まとめ)
  - [一覧](#一覧)
  - [プログラム全体](#プログラム全体)


# 行列
今回は、機械学習には不可欠な行列の計算についてです。

## 行列の作成

### mxn行列
```math
A = \begin{pmatrix}
1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}
```

**Python**
Pythonでは、数値計算ライブラリNumPyを使います（`import numpy`）。Numpyはよく`np`と略して書かれます（`import numpy as np`）。Numpyの2次元配列として行列を使用します。

```Python:Python3
import numpy as np

A = np.array(range(1,12+1))
print(A)
# [ 1  2  3  4  5  6  7  8  9 10 11 12]
A = np.array(range(1,12+1)).reshape(3,4)
A = np.array(range(1,12+1)).reshape(3,-1)
A = np.array(range(1,12+1)).reshape(-1,4)
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

A = np.array([[1,2,3,4],
              [5,6,7,8],
              [9,10,11,12]])
A = np.array([np.array(range(1,4+1)),
              np.array(range(5,8+1)),
              np.array(range(9,12+1))])
A = np.array([np.array(range(1,4+1)),
              np.array(range(1,4+1))+4,
              np.array(range(1,4+1))+8])
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
```

**R**

```R:R
A <- matrix(c(1,2,3,4,5,6,7,8,9,10,11,12), 3, 4, byrow=TRUE)
A <- matrix(1:12, nrow=3, ncol=4, byrow=TRUE)
A <- matrix(1:12, nr=3, nc=4, b=T)
A <- matrix(1:12, 3, 4, byrow=TRUE)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

A <- rbind(c(1,2,3,4),c(5,6,7,8),c(9,10,11,12))
A <- rbind(1:4,5:8,9:12)
A <- rbind(1:4,1:4+4,1:4+8)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

A <- cbind(c(1,5,9),c(2,6,10),c(3,7,11),c(4,8,12))
A <- cbind(c(1,5,9),c(1,5,9)+1,c(1,5,9)+2,c(1,5,9)+3)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12
```

**VBA**
VBAでは、例えばExcelのワークシートの`B3:E5`セル範囲に行列 A が入力されているときは次のようにして配列`A`に値を取り込めます。このとき、配列`A`は2次元で、インデックスは 1 から 3 と 1 から 4 となります。 

```VBA:VBA
Dim A As Variant
A = Range("B3:E5").Value
```

### 単位行列
```math
I_3 = \begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}
```

**Python**

```Python:Python3
print(np.eye(3))
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]
```
`eye`はおそらく単位行列 $I$ （アイ）のこと。

**R**

```R:R
diag(3)
diag(1, 3)
diag(1, 3, 3)
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    0    1    0
# [3,]    0    0    1
```

**VBA**
VBAでは、WorksheetFunction（Excelのワークシート関数）の `Munit` を使えます。

```VBA:VBA
Dim Eye3 As Variant
Eye3 = WorksheetFunction.Munit(3)
```


### ゼロ行列
```math
O = \begin{pmatrix}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0
\end{pmatrix}
```

**Python**

```Python:Python3
print(np.zeros((3,4)))
# [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]
```

**R**

```R:R
matrix(0, 3, 4)
diag(0, 3, 4)
#      [,1] [,2] [,3] [,4]
# [1,]    0    0    0    0
# [2,]    0    0    0    0
# [3,]    0    0    0    0
diag(0, 3)
#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    0    0    0
# [3,]    0    0    0
```

**VBA**

```VBA:VBA
```

### 対角行列
```math
D = \begin{pmatrix}
1 & 0 & 0 \\
0 & 2 & 0 \\
0 & 0 & 3
\end{pmatrix}
```

**Python**

```Python:Python3
print(np.diag([1,2,3]))
# [[1 0 0]
#  [0 2 0]
#  [0 0 3]]
```

**R**

```R:R
diag(c(1,2,3))
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    0    2    0
# [3,]    0    0    3
```

**VBA**

```VBA:VBA
```

### その他


**Python**
Pythonではこういう行列を作る関数もあります。

```Python:Python3
print(np.ones((3,4)))
# [[1. 1. 1. 1.]
#  [1. 1. 1. 1.]
#  [1. 1. 1. 1.]]

print(np.full((3,4), 5))
# [[5 5 5 5]
#  [5 5 5 5]
#  [5 5 5 5]]
```

## 行列の属性

```math
A = \begin{pmatrix}
1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}
```

**Python**

```Python:Python3
A = np.array(range(1,12+1)).reshape(3,4)
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

print(A.shape)    # (行数,列数)
# (3, 4)
print(len(A))
print(A.shape[0]) # 行数
# 3
print(A.shape[1]) # 列数
# 4
print(A.ndim)     # 次元（行列は2次元）
# 2
print(type(A))
# <class 'numpy.ndarray'>
print(A.dtype)
# int32
```

**R**

```R:R
A <- matrix(1:12, 3, 4, byrow=TRUE)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

nrow(A)   # 行数
# 3
ncol(A)   # 列数
# 4
dim(A)    # 行数, 列数
# 3 4
class(A)
# "matrix"
typeof(A)
# "integer"
```

**VBA**
例えばExcelのワークシートの`B3:E5`セル範囲に行列 A が入力されているとします。
配列`A`は2次元で、インデックスは 1 から 3 と 1 から 4 となります。 

```VBA:VBA
Dim A As Variant
A = Range("B3:E5").Value
' 行列の行数
Debug.Print LBound(A, 1), UBound(A, 1), UBound(A, 1) - LBound(A, 1) + 1
' 行列の列数
Debug.Print LBound(A, 2), UBound(A, 2), UBound(A, 2) - LBound(A, 2) + 1
```

## 行列の要素の取得
```math
A = \begin{pmatrix}
1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}
```

**Python**

```Python:Python3
A = np.array(range(1,12+1)).reshape(3,4)
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

# 成分
print(A[0,1])
print(A[1-1,2-1])
print(A[0][1])
# 2

# 行ベクトル
print(A[0,:])
# [1 2 3 4]

# 列ベクトル
print(A[:,1])
# [ 2  6 10]

# 一部取り出し
print(A[[0],:])
# [[1 2 3 4]]

print(A[:,[1]])
# [[ 2]
#  [ 6]
#  [10]]

print(A[0:2,])
# [[1 2 3 4]
#  [5 6 7 8]]

print(A[:,1:4])
# [[ 2  3  4]
#  [ 6  7  8]
#  [10 11 12]]

print(A[-2:,:])
# [[ 5  6  7  8]
#  [ 9 10 11 12]]

print(A[:,-2:])
# [[ 3  4]
#  [ 7  8]
#  [11 12]]

print(A[1:3, 2:4])
# [[ 7  8]
#  [11 12]]

print(A[[0,2],:])
# [[ 1  2  3  4]
#  [ 9 10 11 12]]

print(A[:,[1,3]])
# [[ 2  4]
#  [ 6  8]
#  [10 12]]

print(A[[0,2],[1,3]])   # これはうまくいかない
# [ 2 12]
print(A[np.ix_([0,2],[1,3])])
# [[ 2  4]
#  [10 12]]
print(np.ix_([0,2],[1,3]))
# (array([[0],
#        [2]]), array([[1, 3]]))

print(A[:,:])
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
```

**R**

```R:R
A <- matrix(1:12, 3, 4, byrow=TRUE)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

# 成分
A[1,2]
# [1] 2

# 行ベクトル
A[1,]
# [1] 1 2 3 4

# 列ベクトル
A[,2]
# [1]  2  6 10

# 一部取り出し
A[1:2,]
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8

A[,2:3]
#      [,1] [,2]
# [1,]    2    3
# [2,]    6    7
# [3,]   10   11

A[2:3,3:4]
#      [,1] [,2]
# [1,]    7    8
# [2,]   11   12

A[c(1,3),]
# 
# [1,]    1    2    3    4
# [2,]    9   10   11   12

A[,c(2,4)]
#      [,1] [,2]
# [1,]    2    4
# [2,]    6    8
# [3,]   10   12

A[c(1,3),c(2,4)]
#      [,1] [,2]
# [1,]    2    4
# [2,]   10   12

A[,]
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

head(A)
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12
head(A, 2)
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
tail(A, 2)
#      [,1] [,2] [,3] [,4]
# [2,]    5    6    7    8
# [3,]    9   10   11   12
```

**VBA**
例えばExcelのワークシートの`B3:E5`セル範囲に行列 A が入力されているとします。

```VBA:VBA
Dim A As Variant
A = Range("B3:E5").Value
' 行列の(1, 2)成分
Debug.Print A(1, 2)
```


## 行列の計算

### 線形代数の計算

```math
A = \begin{pmatrix}
1 & 2  \\
3 & 4
\end{pmatrix}
,
B = \begin{pmatrix}
5 & 6  \\
7 & 8
\end{pmatrix}
```

```math
k = 2,
kA = \begin{pmatrix}
2 & 4 \\
6 & 8
\end{pmatrix}
```

```math
A + B = \begin{pmatrix}
6 & 8 \\
10 & 12
\end{pmatrix}
,
AB = \begin{pmatrix}
19 & 22 \\
43 & 50
\end{pmatrix}
```

```math
A^T = \begin{pmatrix}
1 & 3 \\
2 & 4
\end{pmatrix}
,
A^{-1} = \begin{pmatrix}
-2 & 1 \\
1.5 & -0.5
\end{pmatrix}
```

```math
detA = -2
,
trA = 5
```

**Python**

```Python:Python3
A = np.array(range(1,4+1)).reshape(2,2)
print(A)
# [[1 2]
#  [3 4]]
B = np.array(range(5,8+1)).reshape(2,2)
print(B)
# [[5 6]
#  [7 8]]

# 行列のスカラー倍
k = 2
print(A * k)
# [[2 4]
#  [6 8]]

# 行列の和
print(A + B)
# [[ 6  8]
#  [10 12]]

# 行列の積
print(A @ B)
# [[19 22]
#  [43 50]]
print(np.dot(A, B))
# [[19 22]
#  [43 50]]

# 転置行列
print(A.transpose())
# [[1 3]
#  [2 4]]
print(A.T)
# [[1 3]
#  [2 4]]

# 逆行列
print(np.linalg.inv(A))
# [[-2.   1. ]
#  [ 1.5 -0.5]]

# 単位行列
print(np.eye(2))
# [[1. 0.]
#  [0. 1.]]

# 行列式 detA
print(np.linalg.det(A))
# -2.0000000000000004

# 対角成分
print(np.diag(A))
# [1 4]

# トレース（対角成分の和） trA
print(sum(np.diag(A)))
# 5

# 行列のフラット化（ベクトル化）
print(A.flatten())
# [1 2 3 4]

# 行列の変形
print(A.reshape(1,4))
# [[1 2 3 4]]
print(A.reshape(4,1))
# [[1]
#  [2]
#  [3]
#  [4]]
```

**R**

```R:R
A <- matrix(1:4, 2, 2, TRUE)
A
#      [,1] [,2]
# [1,]    1    2
# [2,]    3    4

B <- matrix(5:8, 2, 2, T)
B
#      [,1] [,2]
# [1,]    5    6
# [2,]    7    8

# 行列のスカラー倍
k <- 2
A * k
#      [,1] [,2]
# [1,]    2    4
# [2,]    6    8

# 行列の和
A + B
#      [,1] [,2]
# [1,]    6    8
# [2,]   10   12

# 行列の積
A %*% B
#      [,1] [,2]
# [1,]   19   22
# [2,]   43   50

# 転置行列
t(A)
#      [,1] [,2]
# [1,]    1    3
# [2,]    2    4

# 逆行列
solve(A)
#      [,1] [,2]
# [1,] -2.0  1.0
# [2,]  1.5 -0.5

# 単位行列
diag(2)
#      [,1] [,2]
# [1,]    1    0
# [2,]    0    1

# 行列式 detA
det(A)
# -2

# 対角成分
diag(A)
# [1] 1 4

# トレース（対角成分の和） trA
sum(diag(A))
# 5
```

**VBA**
例えばExcelのワークシートの`B3:C5`セル範囲に行列 A が、`B8:C9`セル範囲に行列 B がそれぞれ入力されているとします。

```VBA:VBA
Dim A As Variant
Dim B As Variant
Dim k As Double
Dim kA As Variant
Dim ApB As Variant
Dim AB As Variant
Dim At As Variant
Dim Ainv As Variant
Dim Eye2 As Variant
Dim detA As Double
Dim trA As Double
Dim i As Integer
Dim j As Integer

' 行列
A = Range("B3:E5").Value
B = Range("B8:C9").Value

' 行列の行数
Debug.Print LBound(A, 1), UBound(A, 1), UBound(A, 1) - LBound(A, 1) + 1

' 行列の列数
Debug.Print LBound(A, 2), UBound(A, 2), UBound(A, 2) - LBound(A, 2) + 1

' 行列の要素 A(1, 2)
Debug.Print A(1, 2)

' 行列のスカラー倍 kA
k = 2
ReDim kA(LBound(A, 1) To UBound(A, 1), LBound(A, 2) To UBound(A, 2))
For i = LBound(A, 1) To UBound(A, 1)
    For j = LBound(A, 2) To UBound(A, 2)
        kA(i, j) = A(i, j) * k
    Next j
Next i
Range("E13:F14").Value = kA

' 行列の和 A+B
ReDim ApB(LBound(A, 1) To UBound(A, 1), LBound(A, 2) To UBound(A, 2))
For i = LBound(A, 1) To UBound(A, 1)
    For j = LBound(A, 2) To UBound(A, 2)
        ApB(i, j) = A(i, j) + B(i, j)
    Next j
Next i
Range("E18:F19").Value = ApB

' 行列の積 AB
AB = WorksheetFunction.MMult(A, B)
Range("E18:F19").Value = AB

' 転置行列 A^T
At = WorksheetFunction.Transpose(A)
Range("E28:F29").Value = At

' 逆行列 A^(-1)
Ainv = WorksheetFunction.MInverse(A)
Range("E33:F34").Value = Ainv

' 単位行列
Eye2 = WorksheetFunction.Munit(2)
Range("E38:F39").Value = Eye2

' 行列式 detA
detA = WorksheetFunction.MDeterm(A)
Range("E42").Value = detA

' トレース trA
trA = WorksheetFunction.SumProduct(A, Eye2)
Range("E45").Value = trA
```


### 要素ごとの演算
Python、Rでは、線形代数の計算とは別に、スカラーの演算と同じ書き方で要素ごとの計算ができます。

**Python**

```Python:Python3
print(A + B)
# [[ 6  8]
#  [10 12]]

print(A - B)
# [[-4 -4]
#  [-4 -4]]

print(A * B)
# [[ 5 12]
#  [21 32]]

print(A / B)
# [[0.2        0.33333333]
#  [0.42857143 0.5       ]]

print(A * 2)
# [[2 4]
#  [6 8]]

print(A ** 2)
# [[ 1  4]
#  [ 9 16]]

print(-A)
# [[-1 -2]
#  [-3 -4]]

print(A == B)
# [[False False]
#  [False False]]

print(A > 2)
# [[False False]
#  [ True  True]]

print(A % 2 == 0)
# [[False  True]
#  [False  True]]

print(np.exp(A))
# [[ 2.71828183  7.3890561 ]
#  [20.08553692 54.59815003]]

print(np.log(A))
# [[0.         0.69314718]
#  [1.09861229 1.38629436]]
```

**R**

```R:R
A + B
#      [,1] [,2]
# [1,]    6    8
# [2,]   10   12

A - B
#      [,1] [,2]
# [1,]   -4   -4
# [2,]   -4   -4

A * B
#      [,1] [,2]
# [1,]    5   12
# [2,]   21   32

A / B
#           [,1]      [,2]
# [1,] 0.2000000 0.3333333
# [2,] 0.4285714 0.5000000

A * 2
#      [,1] [,2]
# [1,]    2    4
# [2,]    6    8

A ^ 2
#      [,1] [,2]
# [1,]    1    4
# [2,]    9   16

-A
#      [,1] [,2]
# [1,]   -1   -2
# [2,]   -3   -4

A == B
#       [,1]  [,2]
# [1,] FALSE FALSE
# [2,] FALSE FALSE

A < B
#      [,1] [,2]
# [1,] TRUE TRUE
# [2,] TRUE TRUE

A > 2
#       [,1]  [,2]
# [1,] FALSE FALSE
# [2,]  TRUE  TRUE

A %% 2 == 0
#       [,1] [,2]
# [1,] FALSE TRUE
# [2,] FALSE TRUE

exp(A)
#           [,1]      [,2]
# [1,]  2.718282  7.389056
# [2,] 20.085537 54.598150

log(A)
#          [,1]      [,2]
# [1,] 0.000000 0.6931472
# [2,] 1.098612 1.3862944
```

**VBA**
VBAでは、`for`文で`(i, j)`成分ごとに計算すればよいだけです。

```VBA:VBA
```



# まとめ
### 一覧
各言語で使用する関数等を一覧にまとめます。比較のために、EXCELでの計算も示しました。
Pythonでは、Numpyを使います（`import numpy as np`）。

***行列の作成***

```math
A = \begin{pmatrix}
1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}
,
I_3 = \begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}
```
```math
O = \begin{pmatrix}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0
\end{pmatrix}
,
D = \begin{pmatrix}
1 & 0 & 0 \\
0 & 2 & 0 \\
0 & 0 & 3
\end{pmatrix}
```

|行列|Python|R|VBA|EXCEL|
|:--|:--|:--|:--|:--|
|mxn行列<br>$A$|`np.array(range(1,12+1)).`<br>`reshape(3,4)`<br>`np.array([`<br>　`[1,2,3,4],`<br>　`[5,6,7,8],`<br> 　`[9,10,11,12]])`|`matrix(1:12,3,4,TRUE)`<br>`rbind(c(1,2,3,4),`<br>　　　 `c(5,6,7,8),`<br>　　　 `c(9,10,11,12))`<br>`cbind(c(1,5,9),`<br>　　　 `c(2,6,10),`<br>　　　 `c(3,7,11),`<br>　　　 `c(4,8,12))`||
|単位行列<br>$I_3$|`np.eye(3)`|`diag(3)`<br>`diag(1, 3)`<br>`diag(1, 3, 3)`|`WorksheetFunction.`<br>`Munit(3)`|`MUNIT(3)`|
|ゼロ行列<br>$O$|`np.zeros((3,4))`|`matrix(0, 3, 4)`<br>`diag(0, 3, 4)`<br>`diag(0, 3)`|||
|対角行列<br>$D$|`np.diag([1,2,3]`|`diag(c(1,2,3))`|||
|１埋め行列|`np.ones((3,4))`||||
|数値埋め行列|`np.full((3,4), 5)`||||

***行列の属性***

```math
A = \begin{pmatrix}
1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}
```

||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|
|形|`A.shape`|`dim(A)`|||3, 4|
|行数|`len(A)`<br>`A.shape[0]`|`nrow(A)`|`UBound(A, 1)`||3|
|列数|`A.shape[1]`|`ncol(A)`|`UBound(A, 2)`||4|
|次元(=2)|`A.ndim`||||2|
|タイプ|`type(A)`|`class(A)`|||
|データ型|`A.dtype`|`typeof(A)`|||

***行列の要素***

```math
A = \begin{pmatrix}
1 & 2 & 3 & 4 \\
5 & 6 & 7 & 8 \\
9 & 10 & 11 & 12
\end{pmatrix}
```
 
||Python|R|VBA|EXCEL|
|:--|:--|:--|:--|:--|
|(1,2)成分|`A[0,1]`<br>`A[0][1]`|`A[1,2]`|`A(1,2)`|=INDEX(A,1,2)|
|1行目の行ベクトル|`A[0,:]`<br>`A[[0],:]`|`A[1,]`|||
|2列目の列ベクトル|`A[:,1]`<br>`A[:,[1]]`|`A[,2]`|||
|1~2行|`A[0:2,]`|`A[1:2,]`|||
|3~4列|`A[:,2:4]`<br>`A[:,-2:]`|`A[,3:4]`|||
|1~2行,3~4列|`A[0:2,2:4]`<br>`A[:2,-2:]`|`A[1:2,3:4]`|||
|1・3行|`A[[0,2],:]`|`A[c(1,3),]`|||
|2・4列|`A[:,[1,3]]`|`A[,c(2,4)]`|||
|1・3行,2・4列|`A[np.ix_([0,2],[1,3])]`|`A[c(1,3),c(2,4)]`|||
|全行,全列|`A[:,:]`|`A[,]`|||
|head||`head(A)`<br>`head(A, 2)`|||
|tail||`tail(A)`<br>`tail(A, 2)`|||

***線形代数の計算***

```math
A = \begin{pmatrix}
1 & 2  \\
3 & 4
\end{pmatrix}
,
B = \begin{pmatrix}
5 & 6  \\
7 & 8
\end{pmatrix}
```

```math
k = 2,
kA = \begin{pmatrix}
2 & 4 \\
6 & 8
\end{pmatrix}
```

```math
A + B = \begin{pmatrix}
6 & 8 \\
10 & 12
\end{pmatrix}
,
AB = \begin{pmatrix}
19 & 22 \\
43 & 50
\end{pmatrix}
```

```math
A^T = \begin{pmatrix}
1 & 3 \\
2 & 4
\end{pmatrix}
,
A^{-1} = \begin{pmatrix}
-2 & 1 \\
1.5 & -0.5
\end{pmatrix}
```

```math
detA = -2
,
trA = 5
```

||Python|R|VBA|EXCEL|
|:--|:--|:--|:--|:--|
|スカラー倍<br>$kA$|`A * k`|`A * k`||`=セル*k`|
|行列の和<br>$A+B$|`A + B`|`A + B`||`=セル+セル`|
|行列の積<br>$AB$|`A @ B`<br>`np.dot(A, B)`|`A %*% B`|`WorksheetFunction.`<br>`MMult(A, B)`|`=MMULT(A,B)`|
|転置行列<br>$A^T$|`A.transpose()`<br>`A.T`|`t(A)`|`WorksheetFunction.`<br>`Transpose(A)`|`=Transpose(A)`|
|逆行列<br>$A^{-1}$|`np.linalg.inv(A)`|`solve(A)`|`WorksheetFunction.`<br>`MInverse(A)`|`=MINVERSE(A)`|
|単位行列<br>$I_2$|`np.eye(2)`|`diag(2)`|`WorksheetFunction.`<br>`Munit(2)`|`=MUNIT(2)`|
|行列式<br>$detA$|`np.linalg.det(A)`|`det(A)`|`WorksheetFunction.`<br>`MDeterm(A)`|`=MDETERM(A)`|
|トレース<br>$trA$|`sum(np.diag(A))`|`sum(diag(A))`|`WorksheetFunction.`<br>`SumProduct(A,Eye2)`||
|対角成分|`np.diag(A)`|`diag(A)`|||
|行列のフラット化|`A.flatten()`||||
|行列の変形|`A.reshape(1,4)`||||

***行列の要素ごとの演算***

||Python|R|VBA|EXCEL|
|:--|:--|:--|:--|:--|
|和|`A + B`|`A + B`||`=セル+セル`|
|差|`A - B`|`A - B`||`=セル-セル`|
|積|`A * B`|`A * B`||`=セル*セル`|
|商|`A / B`|`A / B`||`=セル/セル`|
|スカラー倍|`A * 2`|`A * 2`||`=セル*2`|
|べき乗|`A ** 2`|`A ^ 2`||`=セル^2`|
|符号反転|`-A`|`-A`||`=-セル`|
|等号|`A == B`|`A == B`||`=セル=セル`|
|不等号|`A < B`|`A < B`||`=セル<セル`|
|不等号|`A > 2`|`A > 2`||`=セル>2`|
|余り0|`A % 2 == 0`|`A %% 2 == 0`||`=MOD(セル,2)=0`|
|平方根|`np.sqrt(A)`|`sqrt(A)`||`=SQRT(セル)`|
|exp|`np.exp(A)`|`exp(A)`||`=EXP(セル)`|
|log|`np.log(A)`|`log(A)`||`=LN(セル)`|


### プログラム全体
参考までに使ったプログラムの全体を示します。

**Python**

```Python:Python3
import numpy as np

# 行列の作成
# mxn行列
A = np.array(range(1,12+1))
print(A)
# [ 1  2  3  4  5  6  7  8  9 10 11 12]
A = np.array(range(1,12+1)).reshape(3,4)
A = np.array(range(1,12+1)).reshape(3,-1)
A = np.array(range(1,12+1)).reshape(-1,4)
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

A = np.array([[1,2,3,4],
              [5,6,7,8],
              [9,10,11,12]])
A = np.array([np.array(range(1,4+1)),
              np.array(range(5,8+1)),
              np.array(range(9,12+1))])
A = np.array([np.array(range(1,4+1)),
              np.array(range(1,4+1))+4,
              np.array(range(1,4+1))+8])
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

# 単位行列
print(np.eye(3))
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

# ゼロ行列
print(np.zeros((3,4)))
# [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]
print(np.zeros((3,3)))
# [[0. 0. 0.]
#  [0. 0. 0.]
#  [0. 0. 0.]]

# 対角行列
print(np.diag([1,2,3]))
# [[1 0 0]
#  [0 2 0]
#  [0 0 3]]

# その他
print(np.ones((3,4)))
# [[1. 1. 1. 1.]
#  [1. 1. 1. 1.]
#  [1. 1. 1. 1.]]

print(np.full((3,4), 5))
# [[5 5 5 5]
#  [5 5 5 5]
#  [5 5 5 5]]


# 行列の属性
A = np.array(range(1,12+1)).reshape(3,4)
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

print(A.shape)    # (行数,列数)
# (3, 4)
print(len(A))
print(A.shape[0]) # 行数
# 3
print(A.shape[1]) # 列数
# 4
print(A.ndim)     # 次元（行列は2次元）
# 2
print(type(A))
# <class 'numpy.ndarray'>
print(A.dtype)
# int32


# 行列の要素の取得
A = np.array(range(1,12+1)).reshape(3,4)
print(A)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

# 成分
print(A[0,1])
print(A[1-1,2-1])
print(A[0][1])
# 2

# 行ベクトル
print(A[0,:])
# [1 2 3 4]

# 列ベクトル
print(A[:,1])
# [ 2  6 10]

print(A[[0],:])
# [[1 2 3 4]]

print(A[:,[1]])
# [[ 2]
#  [ 6]
#  [10]]

print(A[0:2,])
print(A[:2,])
# [[1 2 3 4]
#  [5 6 7 8]]

print(A[:,2:4])
print(A[:,-2:])
# [[ 3  4]
#  [ 7  8]
#  [11 12]]

print(A[0:2,2:4])
print(A[:2,-2:])
# [[3 4]
#  [7 8]]

print(A[[0,2],:])
# [[ 1  2  3  4]
#  [ 9 10 11 12]]

print(A[:,[1,3]])
# [[ 2  4]
#  [ 6  8]
#  [10 12]]

print(A[[0,2],[1,3]])   # これはうまくいかない
# [ 2 12]
print(A[np.ix_([0,2],[1,3])])
# [[ 2  4]
#  [10 12]]
print(np.ix_([0,2],[1,3]))
# (array([[0],
#        [2]]), array([[1, 3]]))

print(A[:,:])
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]


# 線形代数の計算
A = np.array(range(1,4+1)).reshape(2,2)
print(A)
# [[1 2]
#  [3 4]]
B = np.array(range(5,8+1)).reshape(2,2)
print(B)
# [[5 6]
#  [7 8]]

# 行列のスカラー倍
k = 2
print(A * k)
# [[2 4]
#  [6 8]]

# 行列の和
print(A + B)
# [[ 6  8]
#  [10 12]]

# 行列の積
print(A @ B)
# [[19 22]
#  [43 50]]
print(np.dot(A, B))
# [[19 22]
#  [43 50]]

# 転置行列
print(A.transpose())
# [[1 3]
#  [2 4]]
print(A.T)
# [[1 3]
#  [2 4]]

# 逆行列
print(np.linalg.inv(A))
# [[-2.   1. ]
#  [ 1.5 -0.5]]

# 単位行列
print(np.eye(2))
# [[1. 0.]
#  [0. 1.]]

# 行列式 detA
print(np.linalg.det(A))
# -2.0000000000000004

# 対角成分
print(np.diag(A))
# [1 4]

# トレース（対角成分の和） trA
print(sum(np.diag(A)))
# 5

# 行列のフラット化（ベクトル化）
print(A.flatten())
# [1 2 3 4]

# 行列の変形
print(A.reshape(1,4))
# [[1 2 3 4]]
print(A.reshape(4,1))
# [[1]
#  [2]
#  [3]
#  [4]]


# 行列の要素ごとの演算
print(A + B)
# [[ 6  8]
#  [10 12]]

print(A - B)
# [[-4 -4]
#  [-4 -4]]

print(A * B)
# [[ 5 12]
#  [21 32]]

print(A / B)
# [[0.2        0.33333333]
#  [0.42857143 0.5       ]]

print(A * 2)
# [[2 4]
#  [6 8]]

print(A ** 2)
# [[ 1  4]
#  [ 9 16]]

print(-A)
# [[-1 -2]
#  [-3 -4]]

print(A == B)
# [[False False]
#  [False False]]

print(A < B)
# [[ True  True]
#  [ True  True]]

print(A > 2)
# [[False False]
#  [ True  True]]

print(A % 2 == 0)
# [[False  True]
#  [False  True]]

print(np.sqrt(A))
# [[1.         1.41421356]
#  [1.73205081 2.        ]]

print(np.exp(A))
# [[ 2.71828183  7.3890561 ]
#  [20.08553692 54.59815003]]

print(np.log(A))
# [[0.         0.69314718]
#  [1.09861229 1.38629436]]
```

**R**

```R:R
# 行列の作成
# mxn行列
A <- matrix(c(1,2,3,4,5,6,7,8,9,10,11,12), 3, 4, byrow=TRUE)
A <- matrix(1:12, nrow=3, ncol=4, byrow=TRUE)
A <- matrix(1:12, nr=3, nc=4, b=T)
A <- matrix(1:12, 3, 4, byrow=TRUE)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12
A <- rbind(c(1,2,3,4),c(5,6,7,8),c(9,10,11,12))
A <- rbind(1:4,5:8,9:12)
A <- rbind(1:4,1:4+4,1:4+8)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12
A <- cbind(c(1,5,9),c(2,6,10),c(3,7,11),c(4,8,12))
A <- cbind(c(1,5,9),c(1,5,9)+1,c(1,5,9)+2,c(1,5,9)+3)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

# 単位行列
diag(3)
diag(1, 3)
diag(1, 3, 3)
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    0    1    0
# [3,]    0    0    1

# ゼロ行列
matrix(0, 3, 4)
diag(0, 3, 4)
#      [,1] [,2] [,3] [,4]
# [1,]    0    0    0    0
# [2,]    0    0    0    0
# [3,]    0    0    0    0
diag(0, 3)
#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    0    0    0
# [3,]    0    0    0

# 対角行列
diag(c(1,2,3))
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    0    2    0
# [3,]    0    0    3


# 行列の属性
A <- matrix(1:12, 3, 4, byrow=TRUE)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

nrow(A)   # 行数
# 3
ncol(A)   # 列数
# 4
dim(A)    # 行数, 列数
# 3 4
class(A)
# "matrix"
typeof(A)
# "integer"


# 行列の要素の取得
A <- matrix(1:12, 3, 4, byrow=TRUE)
A
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

A[1,2]
# [1] 2

# 行ベクトル
A[1,]
# [1] 1 2 3 4

# 列ベクトル
A[,2]
# [1]  2  6 10

# 一部
A[1:2,]
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8

A[,3:4]
#      [,1] [,2]
# [1,]    3    4
# [2,]    7    8
# [3,]   11   12

A[1:2,3:4]
#      [,1] [,2]
# [1,]    3    4
# [2,]    7    8

A[c(1,3),]
# 
# [1,]    1    2    3    4
# [2,]    9   10   11   12

A[,c(2,4)]
#      [,1] [,2]
# [1,]    2    4
# [2,]    6    8
# [3,]   10   12

A[c(1,3),c(2,4)]
#      [,1] [,2]
# [1,]    2    4
# [2,]   10   12

A[,]
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12

head(A)
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
# [3,]    9   10   11   12
head(A, 2)
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    5    6    7    8
tail(A, 2)
#      [,1] [,2] [,3] [,4]
# [2,]    5    6    7    8
# [3,]    9   10   11   12


# 線形代数の計算
A <- matrix(1:4, 2, 2, TRUE)
A
#      [,1] [,2]
# [1,]    1    2
# [2,]    3    4

B <- matrix(5:8, 2, 2, T)
B
#      [,1] [,2]
# [1,]    5    6
# [2,]    7    8

# 行列のスカラー倍
k <- 2
A * k
#      [,1] [,2]
# [1,]    2    4
# [2,]    6    8

# 行列の和
A + B
#      [,1] [,2]
# [1,]    6    8
# [2,]   10   12

# 行列の積
A %*% B
#      [,1] [,2]
# [1,]   19   22
# [2,]   43   50

# 転置行列
t(A)
#      [,1] [,2]
# [1,]    1    3
# [2,]    2    4

# 逆行列
solve(A)
#      [,1] [,2]
# [1,] -2.0  1.0
# [2,]  1.5 -0.5

# 単位行列
diag(2)
#      [,1] [,2]
# [1,]    1    0
# [2,]    0    1

# 行列式 detA
det(A)
# -2

# 対角成分
diag(A)
# [1] 1 4

# トレース（対角成分の和） trA
sum(diag(A))
# 5


# 行列の要素ごとの演算
A + B
#      [,1] [,2]
# [1,]    6    8
# [2,]   10   12

A - B
#      [,1] [,2]
# [1,]   -4   -4
# [2,]   -4   -4

A * B
#      [,1] [,2]
# [1,]    5   12
# [2,]   21   32

A / B
#           [,1]      [,2]
# [1,] 0.2000000 0.3333333
# [2,] 0.4285714 0.5000000

A * 2
#      [,1] [,2]
# [1,]    2    4
# [2,]    6    8

A ^ 2
#      [,1] [,2]
# [1,]    1    4
# [2,]    9   16

-A
#      [,1] [,2]
# [1,]   -1   -2
# [2,]   -3   -4

A == B
#       [,1]  [,2]
# [1,] FALSE FALSE
# [2,] FALSE FALSE

A < B
#      [,1] [,2]
# [1,] TRUE TRUE
# [2,] TRUE TRUE

A > 2
#       [,1]  [,2]
# [1,] FALSE FALSE
# [2,]  TRUE  TRUE

A %% 2 == 0
#       [,1] [,2]
# [1,] FALSE TRUE
# [2,] FALSE TRUE

sqrt(A)
#          [,1]     [,2]
# [1,] 1.000000 1.414214
# [2,] 1.732051 2.000000

exp(A)
#           [,1]      [,2]
# [1,]  2.718282  7.389056
# [2,] 20.085537 54.598150

log(A)
#          [,1]      [,2]
# [1,] 0.000000 0.6931472
# [2,] 1.098612 1.3862944
```

**VBA**

```VBA:VBA
Sub test_matrix()

Dim A As Variant
Dim B As Variant
Dim k As Double
Dim kA As Variant
Dim ApB As Variant
Dim AB As Variant
Dim At As Variant
Dim Ainv As Variant
Dim Eye2 As Variant
Dim detA As Double
Dim trA As Double
Dim i As Integer
Dim j As Integer

' 行列
A = Range("B3:E5").Value
print_matrix (A)

B = Range("B8:C9").Value
print_matrix (B)

' 行列の行数
Debug.Print LBound(A, 1), UBound(A, 1), UBound(A, 1) - LBound(A, 1) + 1

' 行列の列数
Debug.Print LBound(A, 2), UBound(A, 2), UBound(A, 2) - LBound(A, 2) + 1

' 行列の要素 A(1, 2)
Debug.Print A(1, 2)

' 行列のスカラー倍 kA
k = 2
ReDim kA(LBound(A, 1) To UBound(A, 1), LBound(A, 2) To UBound(A, 2))
For i = LBound(A, 1) To UBound(A, 1)
    For j = LBound(A, 2) To UBound(A, 2)
        kA(i, j) = A(i, j) * k
    Next j
Next i
Call print_matrix(kA)
Range("E13:F14").Value = kA

' 行列の和 A+B
ReDim ApB(LBound(A, 1) To UBound(A, 1), LBound(A, 2) To UBound(A, 2))
For i = LBound(A, 1) To UBound(A, 1)
    For j = LBound(A, 2) To UBound(A, 2)
        ApB(i, j) = A(i, j) + B(i, j)
    Next j
Next i
Call print_matrix(ApB)
Range("E18:F19").Value = ApB

' 行列の積 AB
AB = WorksheetFunction.MMult(A, B)
Call print_matrix(AB)
Range("E18:F19").Value = AB

' 転置行列 A^T
At = WorksheetFunction.Transpose(A)
Call print_matrix(At)
Range("E28:F29").Value = At

' 逆行列 A^(-1)
Ainv = WorksheetFunction.MInverse(A)
Call print_matrix(Ainv)
Range("E33:F34").Value = Ainv

' 単位行列
Eye2 = WorksheetFunction.Munit(2)
Call print_matrix(Eye2)
Range("E38:F39").Value = Eye2

' 行列式 detA
detA = WorksheetFunction.MDeterm(A)
Debug.Print detA
Range("E42").Value = detA

' トレース trA
trA = WorksheetFunction.SumProduct(A, Eye2)
Debug.Print trA
Range("E45").Value = trA

End Sub

Sub print_matrix(M As Variant)
' 行列の表示用
Dim i As Integer
Dim j As Integer
Dim s As String

If IsArray(M) Then
    s = ""
    For i = LBound(M, 1) To UBound(M, 1)
        For j = LBound(M, 2) To UBound(M, 2)
            s = s & vbTab & M(i, j)
        Next j
        s = s & vbCrLf
    Next i
    Debug.Print s
End If

End Sub
```


# 参考
- Python
   - [Python チュートリアル](https://docs.python.org/ja/3/tutorial/index.html)
   - [Chainer チュートリアル　8. NumPy 入門](https://tutorials.chainer.org/ja/08_Introduction_to_NumPy.html)
- R
   - [RjpWiki](http://www.okadajp.org/RWiki/)
   - [R-Tips](http://cse.naro.affrc.go.jp/takezawa/r-tips/r.html)