VBAユーザがPython・Rを使ってみた：基本的な文法

# はじめに

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


**目次**

- [基本的な文法](#基本的な文法)
   - [変数の宣言](#変数の宣言)
   - [大文字と小文字の区別](#大文字と小文字の区別)
   - [ステートメントの区切り](#ステートメントの区切り)
      - [複数行を１行にまとめて書く](#複数行を１行にまとめて書く)
      - [１行を複数行に分けて書く](#１行を複数行に分けて書く)
   - [スペースなど](#スペースなど)
      - [スペース](#スペース)
      - [インデント](#インデント)
   - [コメント](#コメント)
   - [代入](#代入)
      - [複合代入演算子](#複合代入演算子)
   - [制御構文](#制御構文)
      - [条件分岐](#条件分岐)
      - [繰り返し](#繰り返し)
   - [基本的な演算](#基本的な演算)
   - [関数](#関数)
   - [ディレクトリ操作等](#ディレクトリ操作等)
      - [カレントディレクトリ](#カレントディレクトリ)
      - [ファイル一覧](#ファイル一覧)
- [まとめ](#まとめ)
  - [一覧](#一覧)
  - [プログラム全体](#プログラム全体)


# 基本的な文法
今回は、基本的な文法についてまとめます。

## 変数の宣言
まず、変数の宣言についてです。

**Python**
Pythonでは、変数を宣言しないで使えます。

**R**
Rでは、変数を宣言しないで使えます。

**VBA**
VBAでは、変数を宣言して使います。（宣言しなくても使えますが。）
モジュールの先頭に `Option Explicit` と記述しておくと、変数の宣言を強制することができます（宣言していない変数が使われているときエラーを出してくれます。）。
変数の宣言は、`Dim x As Integer`, `Dim s As String` のように `Dim 変数名 As 変数型` の形で宣言します。

```VBA:VBA
Option Explicit

Sub test_grammar()
Dim x As Integer
Dim s As String

End Sub
```


## 大文字と小文字の区別
変数名などにおける大文字と小文字の区別についてです。

**Python**
Pythonでは、大文字と小文字は区別されます。

```Python:Python3
x = 1
X = 2
print(x)   # 1
print(X)   # 2
```

**R**
Rでは、大文字と小文字は区別されます。

```R:R
x <- 1
X <- 2
print(x)   # 1 
print(X)   # 2
```

**VBA**
VBAでは、大文字と小文字は区別されません。

```VBA:VBA
x = 1
X = 2
```
VBEではこのように大文字と小文字を区別して書けません。


## ステートメントの区切り
Python、R、VBAとも、基本的に命令（処理）は行単位で区切って書きます。

### 複数行を１行にまとめて書く
どうしても複数の命令（複数の処理）を１行にまとめて書きたいときについてです。

**Python**
Pythonでは、（複数の処理）を`;`（セミコロン）区切りで１行に書くこともできます。

```Python:Python3
x = 1; y = 2
print(x)   # 1
print(y)   # 2

z = 3; print(z)   # 3
```

**R**
Rでは複数行（複数の処理）を`;`（セミコロン）区切りで１行に書くこともできます。

```R:R
x <- 1; y <- 2
x   # 1
y   # 2

z <- 3; print(z)   # 3
```

**VBA**
VBAでは、複数行（複数の処理）を`:`（コロン）区切りで１行に書くこともできます。

```VBA:VBA
x = 1: y = 2
Debug.Print x   ' 1
Debug.Print y   ' 2

z = 3: Debug.Print z   ' 3
```

### １行を複数行に分けて書く
逆に、１行が長くなって見づらかったりして複数行に分けて書きたいときについてです。
引数の区切りなどの `,`（カンマ）で改行して書くのはどの言語でも大丈夫です。それ以外では：

**Python**
Pythonでは、`\`（バックスラッシュ）で改行できます。

```Python:Python3
x = 1 + 2 + \
    3
print(x)   # 6

x = 1 + 2 \
    + 3
print(x)   # 6

s = "abc" + "def" + \
    "ghi"
print(s)   # abcdefghi

s = "abc" + "def" \
    + "ghi"
print(s)   # abcdefghi
```

**R**
Rでは、こういうことはできます。

```R:R
x <- 1 + 2 +
     3
x   # 6
```

**VBA**
VBAでは、`_`（アンダーバー）で改行できます。

```VBA:VBA
x = 1 + 2 _
    + 3
Debug.Print x   ' 6

x = 1 + 2 + _
    3
Debug.Print x   ' 6

s = "abc" & "def" & _
    "ghi"
Debug.Print s   ' abcdefghi

s = "abc" & "def" _
    & "ghi"
Debug.Print s   ' abcdefghi
```

## スペースなど
### スペース
演算子や括弧の前後のスペースなどについてです。

**Python**
Pythonでは、演算子や括弧の前後のスペースはかなり自由に書けます。

```Python:Python3
x=1+2+3
x = 1 + 2  +  3
abs(x)
abs ( x )
```

**R**
Rでは、演算子や括弧の前後のスペースはかなり自由に書けます。

```R:R
x<-1+2+3
x <- 1 + 2  +  3
abs(x)
abs ( x )
```

**VBA**
VBAでは、あまり自由には書けません。VBEで書くときには自動的に調整されます。

```VBA:VBA
x = 1 + 2
Debug.Print Abs(x)
```

### インデント
インデント（字下げ）についてです。

**Python**
Pythonでは、インデントに意味があります。[制御構文](#制御構文)などでブロックを表します。

**R**
Rでは、インデントには意味がありませんので、自由にできます。

**VBA**
VBAでは、インデントには意味がありませんので、自由にできます。


## コメント
コメントの書き方です。

**Python**
Pythonでは、`#`（シャープ）の後にコメントを書けます。`#`の後からその行の終わりまでがコメントアウトされます。

```Python:Python3
# ここはコメントです。
x = 1   # xについてのコメント
print(x)   # 1
```
Jupyter Notebook では、`Ctrl + /` でその行頭に`#`が挿入されます（その行全体がコメントアウトされます。）。もう一度 `Ctrl + /` でコメントアウトが解除されます。

**R**
Rでは、`#`（シャープ）の後にコメントを書けます。`#`の後からその行の終わりまでがコメントアウトされます。

```R:R
# ここはコメントです。
x <- 1   # xについてのコメント
print(x)   # 1
```
RStudio では、`Ctrl + Shift + C` でその行頭に`#`が挿入されます（その行全体がコメントアウトされます。）。もう一度 `Ctrl + Shift + C` でコメントアウトが解除されます。
また、`Ctrl + Shift + R` でコメント行を挿入できます。

**VBA**
VBAでは、`'`（アポストロフィー）の後にコメントを書けます。`'`の後からその行の終わりまでがコメントアウトされます。

```VBA:VBA
' ここはコメントです。
x = 1   ' xについてのコメント
Debug.Print x   ' 1
```


## 文字列

**Python**
Pythonでは、文字列の表記にシングルクォーテーション`'``'`囲みもダブルクォーテーション`"``"`も使えます。
 
```Python:Python3
# 文字列
s = 'abc'
print(s)   # abc
s = "abc"
print(s)   # abc
```

**R**
Rでは、文字列の表記にシングルクォーテーション`'``'`囲みもダブルクォーテーション`"``"`囲みも使えます。

```R:R
s <- 'abc'
print(s)   # "abc"
s <- "abc"
print(s)   # "abc"
```

**VBA**
VBAでは、文字列の表記にダブルクォーテーション`"``"`囲みを使います。

```VBA:VBA
s = "abc"
Debug.Print s
```


## 代入

**Python**
Pythonでは、代入に `=` を使います。
また、Pythonでは、複数の変数に同時に代入することができます（データ型が異なっても構いません。）。

```Python:Python3
x = 1

# 複数同時代入
x, y = 1, 2
print(x, y)   # 1 2
a, b, c = 1, 2, 3
print(a, b, c)   # 1 2 3
a, b, c = 1, 2.345, "abc"
print(a, b, c)   # 1 2.345 abc
```

**R**
Rでは、代入演算子に `<-`、`=`、`->` があります。
`->` は左から右に代入します。複雑な式を書いて最後に代入するときに便利です。

```R:R
x <- 1
print(x)   # 1

x = 2
print(x)   # 2

3 -> x
print(x)   # 3

1 + 2 * (3 - 4) / 5 -> x
print(x)   # 0.6
```

**VBA**
VBAでは代入演算子と比較演算子に同じ記号`=`を使います。
なお、VBAではオブジェクトへの代入は`Set`ステートメントを使います。

```VBA:VBA
x = 1
Debug.Print x   ' 1
```


### 複合代入演算子
演算と代入を合わせて行う複合代入演算子（累算代入演算子、累積代入文）についてです。

**Python**

```Python:Python3
n = 1
n += 1
print(n)   # 2
n -= 1
print(n)   # 1
n *= 2
print(n)   # 2
n /= 2
print(n)   # 1.0

s = "abc"
s *= 3
print(s)   # abcabcabc
```

**R**

```R:R
```
Rには複合代入演算子はなさそうです。

**VBA**

```VBA:VBA
```
VBAには複合代入演算子はなさそうです。


## 出力
変数の値を出力する方法についてです。

**Python**
Pythonでは、`print`関数を使います。

```Python:Python3
x = 1
print(x)   # 1
s = 'abc'
print(s)   # abc
```
Jupyter Notebook 上では、変数名を書いたセルを実行すると、その変数の値が表示されます（セル内に複数ある場合は最後に書いた変数のみ）。

**R**
Rでは、変数名を書いて実行すると、その変数の値が表示されます。また、`print`関数、`cat`関数が使えます。
また、Rでは、代入文を`(``)`で囲むと、代入して出力されます。

```R:R
x <- 1
x          # 1
print(x)   # 1
cat(x)     # 1
s <- "abc"
s          # "abc"
print(s)   # "abc"
cat(s)     # abc

(x <- 1)     # 1
(s <- "abc") # abc"
```

**VBA**
VBAでは、`Debug.Print`でイミディエイトウィンドウへ出力、`MsgBox`でメッセージボックスへの出力ができます。

```VBA:VBA
x = 1
Debug.Print x
MsgBox x
```


## 入力
変数に値を入力する方法についてです。

**Python**
Pythonでは、`input`関数が使えます。

```Python:Python3
x = int(input("xを入力してください。"))
print(x)
```
`input`関数の返り値は文字列（str型）なので、`int`関数でint型に変換しています。

**R**

```R:R
```

**VBA**
VBAでは、`InputBox`関数と`Application.InputBox`メソッドが使えます。

```VBA:VBA
x = InputBox("xを入力してください。")
Debug.Print x

x = Application.InputBox("xを入力してください。")
Debug.Print x
```


## 制御構文
### 条件分岐
条件分岐（主に、if文）については、[こちら](https://qiita.com/swathci/private/2dba6ebf683a11403f12)。

### 繰り返し
繰り返し（主に、for文とwhile文）については、[こちら](https://qiita.com/swathci/items/97de2111e70c10205521)。


## 基本的な演算
算術演算については、[こちら](https://qiita.com/swathci/items/853b48ca75a0935378bb)。
比較演算については、[こちら](https://qiita.com/swathci/items/dfd5e80060ff23416ce5)。
論理演算については、[こちら](https://qiita.com/swathci/items/dfd5e80060ff23416ce5)。


## 関数
標準で使える基本的な関数については、[こちら](https://qiita.com/swathci/items/2d8e00d0e45874fc4686)。


## ディレクトリ操作等
### カレントディレクトリ

**Python**
Pythonでは、カレントワーキングディレクトリ（作業ディレクトリ）の確認には `os`モジュールを使います（`import os`）。`os.getcwd()`でカレントディレクトリの確認、`os.chdir()`でカレントディレクトリを変更できます。

```Python:Python3
import os
os.getcwd()
os.path.abspath(".")
os.chdir('C://Users/test')
```

**R**
Rでは、`getwd`関数でワーキングディレクトリが確認できます。また、`setwd`関数でワーキングディレクトリを設定できます。

```R:R
getwd()
setwd("C:/Users/test")
```

**VBA**
VBAでは、`ThisWorkbook.Path`で実行しているブック（エクセルファイル）のパスが取得できます。

```VBA:VBA
Debug.Print ThisWorkbook.Path
ChDir "C:\Users\test"
```

### ファイル一覧
ディレクトリ内のファイル一覧を表示する方法です。

**Python**
Pythonでは、`os`モジュールを使います。

```Python:Python3
import os
os.listdir()
os.listdir('.')
os.listdir('./data')
os.listdir('..')
```

**R**

```R:R
dir()
list.files(".")
list.files("./data")
list.files("..")
list.dirs(".")
```

**VBA**
VBAでは、PythonやRのように簡単にファイル一覧を表示はできません。

```VBA:VBA
```


# まとめ
### 一覧
各言語の文法等を一覧にまとめます。

***基本的な書き方***

||Python|R|VBA|
|:--|:--|:--|:--|:--|
|変数の宣言|宣言しない|宣言しない|Dim 変数名 As 変数型<br>の形で宣言|
|大文字と小文字の区別|区別あり|区別あり|区別なし|
|複数行を１行にまとめて書く|`;`区切り|`;`区切り|`:`区切り|
|１行を複数行に分けて書く|`/`で改行||`_`で改行|
|スペース|自由|自由|自動的に調整|
|インデント|制御文でブロックを表す|自由|自由|
|コメントアウト|`#`の後|`#`の後|`'`の後|
|文字列|`'``'`囲み<br>`"``"`囲み|`'``'`囲み<br>`"``"`囲み|`"``"`囲み|

***代入***

||Python|R|VBA|
|:--|:--|:--|:--|
|代入|`=`|`<-`<br>`=`<br>`->`|`=`|
|複数同時代入|可能|||
|複合代入演算子|あり|||
|代入後出力||代入文を`(``)`囲み||

***入出力***

||Python|R|VBA|
|:--|:--|:--|:--|
|出力|`print()`|`print()`<br>`cat()`|`Debug.Print`<br>`MsgBox`|
|入力|`input()`||`InputBox()`<br>`Application.InputBox()`|

***ディレクトリ***

||Python|R|VBA|
|:--|:--|:--|:--|
|カレントディレクトリの取得|`import os`<br>`os.getcwd()`|`getwd()`|`Debug.Print ThisWorkbook.Path`|
|カレントディレクトリの変更|`import os`<br>`os.chdir('C://.../...')`|`setwd("C:/.../...")`|`ChDir "C:\...\..."`|
|ファイル一覧の表示|`import os`<br>`os.listdir('.')`|`dir()`||


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

**Python**

```Python:Python3
# 大文字と小文字の区別
x = 1
X = 2
print(x)   # 1
print(X)   # 2


# 複数行を１行にまとめて書く
x = 1; y = 2
print(x)   # 1
print(y)   # 2

z = 3; print(z)   # 3


# １行を複数行に分けて書く
x = 1 + 2 + \
    3
print(x)   # 6

x = 1 + 2 \
    + 3
print(x)   # 6

s = "abc" + "def" + \
    "ghi"
print(s)   # abcdefghi

s = "abc" + "def" \
    + "ghi"
print(s)   # abcdefghi


# スペース
x=1+2+3
x = 1 + 2  +  3
abs(x)
abs ( x )


# コメント
# ここはコメントです。
x = 1   # xについてのコメント
print(x)   # 1


# 文字列
s = 'abc'
print(s)   # abc
s = "abc"
print(s)   # abc


# 代入
x = 1

# 複数同時代入
x, y = 1, 2
print(x, y)   # 1 2
a, b, c = 1, 2, 3
print(a, b, c)   # 1 2 3
a, b, c = 1, 2.345, "abc"
print(a, b, c)   # 1 2.345 abc


# 複合代入演算子
n = 1
n += 1
print(n)   # 2
n -= 1
print(n)   # 1
n *= 2
print(n)   # 2
n /= 2
print(n)   # 1.0

s = "abc"
s *= 3
print(s)   # abcabcabc


# 出力
x = 1
print(x)   # 1
s = 'abc'
print(s)   # abc


# 入力
x = int(input("xを入力してください。"))
print(x)


# カレントディレクトリ
import os
os.getcwd()
os.path.abspath(".")
os.chdir('C://Users/test')


# ファイル一覧
import os
os.listdir()
os.listdir('.')
os.listdir('./data')
os.listdir('..')
```

**R**

```R:R
# 大文字と小文字の区別
x <- 1
X <- 2
print(x)   # 1 
print(X)   # 2


# 複数行を１行にまとめて書く
x <- 1; y <- 2
x   # 1
y   # 2

z <- 3; print(z)   # 3


# １行を複数行に分けて書く
x <- 1 + 2 +
  3
x   # 6


# スペース
x<-1+2+3
x <- 1 + 2  +  3
abs(x)
abs ( x )


# コメント
# ここはコメントです。
x <- 1   # xについてのコメント
print(x)   # 1


# 文字列
s <- 'abc'
print(s)   # "abc"
s <- "abc"
print(s)   # "abc"


# 代入
x <- 1
print(x)   # 1

x = 2
print(x)   # 2

3 -> x
print(x)   # 3

1 + 2 * (3 - 4) / 5 -> x
print(x)   # 0.6


# 出力
x <- 1
x          # 1
print(x)   # 1
cat(x)     # 1
s <- "abc"
s          # "abc"
print(s)   # "abc"
cat(s)     # abc

(x <- 1)     # 1
(s <- "abc") # abc"


# 入力


# カレントディレクトリ
getwd()
setwd("C:/Users/test")


# ファイル一覧
dir()
list.files(".")
list.files("./data")
list.files("..")
list.dirs(".")
```

**VBA**

```VBA:VBA
Option Explicit

Sub test_grammar()
' 変数の宣言
Dim x As Integer
Dim y As Integer
Dim z As Integer
Dim s As String


' 大文字と小文字の区別
x = 1
' X = 2


' 複数行を１行にまとめて書く
x = 1: y = 2
Debug.Print x   ' 1
Debug.Print y   ' 2

z = 3: Debug.Print z   ' 3


' １行を複数行に分けて書く
x = 1 + 2 _
    + 3
Debug.Print x   ' 6

x = 1 + 2 + _
    3
Debug.Print x   ' 6

s = "abc" & "def" & _
    "ghi"
Debug.Print s   ' abcdefghi

s = "abc" & "def" _
    & "ghi"
Debug.Print s   ' abcdefghi


' スペース
x = 1 + 2
Debug.Print Abs(x)


' コメント
' ここはコメントです。
x = 1   ' xについてのコメント
Debug.Print x   ' 1


' 文字列
s = "abc"
Debug.Print s


' 代入
x = 1
Debug.Print x   ' 1


' 出力
x = 1
Debug.Print x
MsgBox x


' 入力
x = InputBox("xを入力してください。")
Debug.Print x

x = Application.InputBox("xを入力してください。")
Debug.Print x


' カレントディレクトリ
Debug.Print ThisWorkbook.Path
'ChDir "C:\Users\test"

End Sub
```


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