Castについて

# そもそもcastとは？
まず英語の意味で見てみましょう。
Cast = 「配役」や「割り当てる」などの意味があります。
よく「豪華キャストで送る〜」みたいな言い方がありますが「豪華配役/出演者」ということですね。
意味を見てわかる通りcastは何かに対して何かを割り当てるということです。
したがってプログラミングでは**castはデータ型の変換**を意味します。
普通、Pythonでは入力したデータに応じて、Pythonが自動的にデータ型を決めてくれます。(動的型付けと言います)
しかし、castをすることによりデータ型を手動で決定/変更することができます。

それではCastをしていきましょう！以下のCastをしていきます
1. 組み込み型(e.x. 数値型、str型)
2. データフレーム型内の要素
3. Array型内の要素
  
# 標準関数のcast e.x. int, str, list 
よく使われる組み込み型
1. bool
2. int
3. float
4. str
5. list
6. tuple
7. dict
ここでは取り上げませんが、他にも組み込み型があります。
興味のある方は下記参照してみてください。
[組み込み型](#https://docs.python.org/ja/3/library/stdtypes.html)

まず、変数の定義をしていきます。(変数名を格データ方の頭文字にしています。)  

~~~python
b = True # bool
i = 5 # int
f = 10.5 # float
s = '55' # str
l = [10, 45, 'Tako'] # list
t = (6, 8.5, 'cat') # tuple
d = {'Mike': 'America', 'Aya': 'Japan', 'sung': 'Korea'} # dict
~~~

意図通りのデータが入っているかデータ型をみていきます。
type(変数)で見ることができます。

```python
print(type(b))
print(type(i))
print(type(f))
print(type(s))
print(type(l))
print(type(t))
print(type(d))
```

```:output
<class 'bool'>
<class 'int'>
<class 'float'>
<class 'str'>
<class 'list'>
<class 'tuple'>
<class 'dict'>
```
意図通りの値が入っています。
次にcastをしていきます。まず、bool, int, float, strを変更してみます。
例) strをintに変換　⇨　int(strの変数)　と書く

~~~python
b_to_i = int(b) # bool  -> int
i_to_s = str(i) # int -> bool
f_to_i = int(f) # float -> int
s_to_f = float(s) # str -> float
~~~
変換完了しました。
実際に変換できているかtype()で見ていきましょう。

```python
print(type(b_to_i))
print(type(i_to_s))
print(type(f_to_i))
print(type(s_to_f))
```

```:output
<class 'int'>
<class 'str'>
<class 'int'>
<class 'float'>
```

castができていますね。
同様の方法でlistやdict内の要素も変換できます。 
ちなみに、bool -> int/floatでもcast可能です。
Trueだと1/1.0でFalseだと0/0.0で表示されます。
またfloat -> intは小数点以下が切り捨てられています。
見てみましょう。

```python
print(b_to_i) # Trueなので1が入っている
print(f_to_i) # 小数点以下切り捨て
```
```:output
1
10
```
Castができない場合

```python
# NG例
s = 'Hello'
not_s_to_i = int(s) # 文字列はcastできない
```
```:output
ValueError                                Traceback (most recent call last)
<ipython-input-21-1313b5f470bf> in <module>
      1 # NG例
      2 s = 'Hello'
----> 3 not_s_to_i = int(s)

ValueError: invalid literal for int() with base 10: 'Hello'
```
数字ではない文字列はint関数ではcastすることができません。

次に他のデータ型からlist、tuple、dictへの変換をしてみましょう。まずは変換される変数の定義とデータ型の確認。

```python
s = 'Hello' # str
l = [10, 45, 'Tako'] # lsit
l2 = [['Mike', 'America'], ['Aya', 'Japan'], ['sung', 'Korea']] # list of list
t = (6, 8.5, 'cat')
print(type(s))
print(type(l))
print(type(l2))
print(type(t))
```
```:output
<class 'str'>
<class 'list'>
<class 'list'>
<class 'tuple'>
```

それではcastをしていきます。
cast後の型とデータもみましょう。

```python
s_to_l = list(s) # str -> list
t_to_l = list(t) # tuple -> list
s_to_t = tuple(s) # str -> tuple
l_to_t = tuple(l) # list -> tuple
l2_to_d = dict(l2) # list of list -> dict

print(type(s_to_l))
print(s_to_l)

print(type(t_to_l))
print(t_to_l)

print(type(s_to_t))
print(s_to_t)

print(type(l_to_t))
print(l_to_t)

print(type(l2_to_d))
print(l2_to_d)
```
```:output
<class 'list'>
['H', 'e', 'l', 'l', 'o']

<class 'list'>
[6, 8.5, 'cat']

<class 'tuple'>
('H', 'e', 'l', 'l', 'o')

<class 'tuple'>
(10, 45, 'Tako')

<class 'dict'>
{'Mike': 'America', 'Aya': 'Japan', 'sung': 'Korea'}

```
str型をlist/tupleに変換する場合、1文字ずつ分解され保存されます。
リストのリストの場合、リストの中の各リストが2つのデータを保有する場合、dict型に変換可能です。
1つ目がKeyになり、2つ目がValueになります。
また、通常のlist/tupleであっても各データが2文字であれば変換可能です。(使用の機会があまりなさそうなので割愛します。)

# PnadasやNumpy
他にもPandasのDataFrameオブジェクトとSeriesオブジェクトの要素をメソッドを使うことで変換できたり、Numpyでもarrayの要素をメソッドを使うことで変換できます。

```python
import pandas as pd
import numpy as np

# pandas例
df = pd.read_csv('./data/cls_train.csv') # Titanic - https://www.kaggle.com/c/titanic/data?select=train.csv
print('変更前: ', df['Age'].dtypes)
df['Age'] = df['Age'].astype(str) # Age列の要素の変換
print('変更後 ', df['Age'].dtypes)

# numpyの例
lst = [52.5, 2, 5, 10.999]
n_array = np.array(lst, dtype=np.float64) # float64型
print('変更前: ', n_array.dtype)
int_arr = n_array.astype('int') # float -> int
print('変更前: ', int_arr.dtype)
```

```:output
変更前: int64
変更後: object
変更前: float64
変更前: int64
```
このように簡単に変更できます。
ちなみにデータフレームはstr型にするとobjectという名前に変わります。
もっと詳しく見たい人は公式ドキュメントを見てください
[Pandas](#https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.astype.html)
[Numpy](#https://numpy.org/doc/stable/reference/generated/numpy.ndarray.astype.html)

# まとめ
さまざまなCast方法がありました。
標準関数を使ってのcastは標準関数(変えたい値)で簡単に変えれれ、pandasとnumpyはastypeメソッドを簡単につかって変換できます。
ここでは触れませんが、int64、int32、int16などビット指定ができてメモリ消費を抑えたり、パソコンの環境に合わせることができます。
個人的な考えですが、castが1番活躍するのは、計算などで数字を扱う時ではないでしょうか？
例えばユーザーからのインプット(input())はstr型になってしまうので、数字のインプットでも計算などで使うことができません。
そのような時にcastを使うことで解決できます。意外と使える技術だと思います。

指摘などありましたら、コメントお願いします。