【Python３】第２回 タイタニックを標準モジュールだけで集計してみた。　～データ型操作練習編～

#概要#
**某データ分析会社による一流のデータサイエンティストを養成するのためのPython研修タイタニック編**
　
<font color="LightSeaGreen">**全ての人間は２種類に分けることが出来る。
　Pythonでデータ型操作が出来る者と、そうでない者。
　   　　　　　　　　　　　　　　@74kenshiro（1988年～2095年）**</font>

**タイタニックのトレインデータをPython３標準モジュールで読込み、加工集計、CSVに出力してみた。
の皆さんお待ちかね第２弾です。**

<font color="Red">今回も初心者ながら上忍目指して頑張るってばよ！</font>

**１．リストから２種類の持ち方の辞書を作る　
２．辞書をCSVに出力する**
##この記事で分かること##
**<font color="Red">pandas</font>を使わずに、<font color="Red">標準モジュール</font>での**
**・リストから辞書を作成する方法
・辞書をCSVに出力する方法
・家族とタイタニック観た時の気まずい空気を圧倒的に打破する方法**

##データ概要
**SIGNATE**
【練習問題】タイタニックの生存予測
https://signate.jp/competitions/102/data
トレインデータ（TSV）
**《データ説明》**

|カラム|ヘッダ名称|データ型|説明|
|-----|----------|-------|----|
0|id|int|インデックスとして使用
1|survived|boolean|生還結果（1=生還, 0=死亡）
2|pclass|int|客室のクラス（1,2,3の順に高級クラス）
3|sex|char|性別
4|age|int|年齢
5|sibsp|int|乗船していた兄弟、配偶者の数
6|parch|int|乗船していた両親、子供の数
7|fare|float|運賃
8|embarked|char|乗船した港（S=Southampton, C=Cherbourg, Q=Queenstown）

**《データ一部抜粋》**
各要素に一部欠損値有り
（下記一部抜粋）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/340189/0b286d7c-84d9-04d2-90ff-94972d05b922.png)




##１．リストから２種類の持ち方の辞書を作る　

前回作成した二次元リスト「list01new」を元にする。
中身は列名（ヘッダー）も含めた各行のリストとなっている。

**前回作成した「list01new」**

```python:list01new：TSVデータを読込み、欠損値をNoneに置換したリスト
list01 = []
list01new = []
# 1.データの読み込み
# 改行\nとタブ区切り\tを削除する
with open("train.tsv", mode="r") as f:
    for line in f:
        list01.append(line.rstrip('\n').split('\t'))
# 2．欠損値をNoneに置換する
# 「''」の場合は「None」、それ以外はそのままとし、list01newにappendする。
for line in list01:
    new_line = []
    for value in line:
        if value == '':
            value_after = None
        else:
            value_after = value
        new_line.append(value_after)
    list01new.append(new_line)

pprint.pprint(list01new[0:3])

print('--------' * 10)
none_list = [row for row in list01none if None in row]
pprint.pprint(none_list[7:9])
```

**OUTPUT：「list01new」の中身** 

```
[['id','survived','pclass','sex','age','sibsp','parch','fare','embarked'],
 ['3', '1', '1', 'female', '35', '1', '0', '53.1', 'S'],
 ['4', '0', '3', 'male', '35', '0', '0', '8.05', 'S']]
 --------------------------------------------------------------------------------
[['47', '1', '3', 'female', None, '0', '0', '7.75', 'Q'],
['61', '1', '1', 'female', '38', '0', '0', '80', None]]
```
###**１．最初に、列名（ヘッダー）を除いた値だけのリストを作る➡【イメージA】**
**【イメージA】
列名（ヘッダー）の行が無い**

```:イメージA
# id,survived,pclass,sex,age,sibsp,parch,fare,embarked
[
  [3, 1, 1, female, 35, 1, 0, 53, 1, s]
  [4, 0, 3, male, 35, 0, 0, 8.05, s]
  [7, 0, 3, male, 2, 3, 1, 21.075, s]
,,,
]
```
**①list01aにlist01newの１番目以降をappend
このままだとリストで括られているので、２重ループ処理で各行に分割し、list01Aにappendする。**


```python

list01a = []
list01A = []
list01a.append(list01new[1:])
for line1 in list01a:
    for line2 in line1:
        list01A.append(line2)
pprint.pprint(list01A)
```
**OUTPUT：イメージA完成** 


```
[['3', '1', '1', 'female', '35', '1', '0', '53.1', 'S'],
 ['4', '0', '3', 'male', '35', '0', '0', '8.05', 'S'],
 ['7', '0', '3', 'male', '2', '3', '1', '21.075', 'S'],
,,,]]
```
###**２．列名（ヘッダー）のリストとイメージAのリスト「list01A」で辞書を作る➡【イメージB】**
**【イメージB】
列名（ヘッダー）がキー、値が各要素の辞書**

```:イメージB
# id,survived,pclass,sex,age,sibsp,parch,fare,embarked
{
  "id":       [3, 4, 7,,,]
  "survived": [0, 1, 1,,,]
  "pclass":   [1, 3, 3,,,]
  "sex":      [female, male, male,,,]
  "age":      [35, 35, 2,,,]
  "sibsp":    [1, 0, 3,,,]
  "parch":    [0, 0, 1,,,]
  "fare":     [53.1, 8.05, 21.075,,,]
  "embarked": [S, S, S,,,]

}
```
**①新たに「list01key」を作り、「list01new」の列名（ヘッダー）だけ定義する。**

```python:list01newの０番目の要素をlist01keyとする
list01key = list01new[0]
print(list01key)

```
**OUTPUT：キーとする列名（ヘッダー）のリスト「list01key」が完成**

```:OUTPUT
['id', 'survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked']
```
**②新たに「list01value]を作り、「list01new」の列名（ヘッダー）ごとの値をappendする。**

```python:②list01valueに値ごとのリストをappendする

list01value = []
for i,key in enumerate(list01key):
    line_list = []
    for j,value in enumerate(list01A):
        a = list01A[j][i]
        line_list.append(a)
    list01value.append(line_list)
pprint.pprint(list01value)

```
**OUTPUT**

```
[['3',
  '4',
  '7',
  '9',
  '11',
  '13',
 ,
 ,
 ]]
```
**③<font color="Green">「list01key」をキー</font> 、<font color="DarkOrange">「list01value」を値</font> とし二つのリストで辞書「dict01B」を作る。**
【基本的なコード】
**作成する辞書 ＝ <font color="Blue">dict(zip(</font><font color="Green">キー</font>となるリスト,<font color="DarkOrange">値</font>となるリスト<font color="Blue">))</font>**

```python:dict(zip(キー,値)の例
key = ['A','B','C']
value = [[1,2,3],[4,5,6],[7,8,9]]
dict = dict(zip(key,value))
print(dict)
   # => {'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}
```
これを先ほど作ったリストでやってみた。

```python
dict01B = dict(zip(list01key,list01value))
pprint.pprint(dict01B)
```

**OUTPUT：でけた。**

```:OUTPUT
{'age': ['35',
         '35',
         '2',
        None],
 'embarked': ['S',
              'S',
              'S',
　　　　　　　,,,　　　　　　
```

###**３．列名（ヘッダー）のリスト「list01key」とイメージAのリスト「list01A」で、１行ごとの辞書「dict01C」を作る➡【イメージC】**
**【イメージC】
キーが列名、値が各要素で１行ごとの辞書。**

```:イメージC
# id, survived, age,,,
[
  {"id": 1, "survived": 0, "age": 35,,,}
  {"id": 2, "survived": 1, "age": 25,,,}
  #...
  {"id": 12, "survived": 1, "age": 25,,,}
]

```
ループ処理で一行ずつ**<font color="Blue">dict(zip(</font><font color="Green">キー</font>となるリスト,<font color="DarkOrange">値</font>となるリスト<font color="Blue">))</font>**で辞書のリスト「lsit01C」を作成する。

```python:イメージCの形にするコード

dict01C = []
for line in list01A:
    d = dict(zip(list01key,line))
    dict01C.append(d)
pprint.pprint(dict01C)
```

**OUTPUT　で、でけた。。**

```
[{'age': '35',
  'embarked': 'S',
  'fare': '53.1',
  'id': '3',
  'parch': '0',
  'pclass': '1',
  'sex': 'female',
  'sibsp': '1',
  'survived': '1'},
 {'age': '35',
  'embarked': 'S',
  'fare': '8.05',
  'id': '4',
  'parch': '0',
  'pclass': '3',
  'sex': 'male',
  'sibsp': '0',
  'survived': '0'},
,
,
,
```

###追記：簡潔バージョン　（2019/02/08）
**読者様からコメント頂いたコードの方が圧倒的簡潔なので紹介させて頂きます。**
元データのリストしか使わずわずか１行で出来るコード。

```python:イメージCの形にするコード簡潔ver.
# 元データ　list01new=
[
['id','survived','pclass','sex','age','sibsp','parch','fare','embarked'],
 ['3', '1', '1', 'female', '35', '1', '0', '53.1', 'S'],
 ['4', '0', '3', 'male', '35', '0', '0', '8.05', 'S']
,
]

list01C=[dict(zip(list01new[0], row)) for row in list01new[1:]]
>>>
[{'age': '35',
  'embarked': 'S',
  'fare': '53.1',
  'id': '3',
  'parch': '0',
  'pclass': '1',
  'sex': 'female',
  'sibsp': '1',
  'survived': '1'},
 {'age': '35',
  'embarked': 'S',
  'fare': '8.05',
  'id': '4',
  'parch': '0',
  'pclass': '3',
  'sex': 'male',
  'sibsp': '0',
  'survived': '0'},
,
,
,
```

##２．辞書をCSVに出力する
###**１.まずはイメージAのリスト「list01A」をやってみる**

```python:イメージA　list01AのCSV出力

with open(r"list01A.csv", "w") as f:
    for row in list01A:
        print(*row, sep=',', file=f)
```
**OUTPUT　OK！
見たまんま、前回やったlist01newの列名（ヘッダー）が無いバージョンである。**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/340189/4bbb42c9-ed7c-ed36-e1c7-5cd94cd148db.png)
###**２.辞書「dict01B」を出力する**
　①リスト「list01A」と同じようにやってみた。

```python:イメージB　dict01BのCSV出力

with open(r"dict01B.csv", "w") as f:
    for row in dict01B:
        print(*row, sep=',', file=f)
```
**OUTPUT：NG
なんか思ってたのと違うっ！！！**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/340189/04eccc14-ee98-1435-104d-1b538e9b69af.png)

　ループ処理で書いてる内容を確認するの巻、、、

```python:何が書かれてるか確認してみるコード
for row in dict01B:
    print(row)
```
**OUTPUT ：NG！
キーだけ出力してた件　そりゃそうだ。**

```:OUTPUT
id
survived
pclass
sex
age
sibsp
parch
fare
embarked
```
**辞書のキーと値を抽出する時は<font color="Blue"> .items()</font>を使うんでした。**　
ループ処理の辞書に**<font color="Blue"> .items()</font>**とインデックスの**変数 <font color="Blue">i</font>**を追加して確認。

```python
for i,row in dict01B.items():
    print(i,row)
```
**OUTPUT：OK!!　
これや！わいが求めてたんはこの形や！！**

```
id ['3', '4', '7', '9', '11', '13', '16', '19', '23', '24', '25', '26', '28', '29', '32', '33', '36', '41', '42', '43', 
survived ['1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '0', '1', '0', '1', '0', '1', '0', '0', '1', '1', '1', 
pclass ['1', '3', '3', '2', '1', '3', '3', '3', '1', '3', '3', '3', '3', '3', '3', '2', '3', '2', '3', '2', '3', '3', 
sex ['female', 'male', 'male', 'female', 'female', 'male', 'male', 'female', 'male', 'female', 'female', 'male', 
age ['35', '35', '2', '14', '58', '39', '2', 'None', '28', '8', '38', 'None', 'None', 'None', 'None', '66', 'None', 
sibsp ['1', '0', '3', '1', '0', '1', '4', '0', '0', '3', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '0', '0', 
parch ['0', '0', '1', '0', '0', '5', '1', '0', '0', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '2', '0', '0', 
fare ['53.1', '8.05', '21.075', '30.0708', '26.55', '31.275', '29.125', '7.225', '35.5', '21.075', '31.3875', '7.225', 
embarked ['S', 'S', 'S', 'C', 'S', 'S', 'Q', 'C', 'S', 'S', 'S', 'C', 'Q', 'S', 'Q', 'S', 'C', 'S', 'C', 'C', 'Q', 'Q', 
```

CSV出力コードに**<font color="Blue"> .items()</font>**と**<font color="Blue">i</font>**、そして、アンパックの``*（アスタリスク）``をrow側につける。

```python:アンパックの例
WTF = ['A','B','C']
print(WTF)
# => [A, B, C]
print(*WTF)
# => A B C
```

```python:dict01BのCSV出力
with open(r"dict01B.csv", "w") as f:
   for i,row in dict01B.items():
        print(i,*row,sep=',',file = f)
```
**OUTPUT：OK
１００点満点の極み。ありがとう<font color="Blue"> .items()</font>、そして <font color="Blue">i </font>、そしてこれを読んでくれている<font color="Red">世界中のエンジニア諸君</font>。**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/340189/1cbcf7de-59c4-1caa-8449-d55a8b718148.png)


###**３.辞書「dict01C」を出力する**
**①「dict01C」は辞書なので、CSV出力用の「list01Cnew」を作成し、ループ処理でキーと、そのキーの値を順にappendする。**

```python:辞書「dict01C」からリスト「list01Cnew」を作る。
# list01key = ['id', 'survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked']
list01Cnew = []
for i in range(len(dict01C)):
    list_dict = []
    for k in list01key:
        list_dict.append(k)
        list_dict.append(dict01C[i][k])
    list01Cnew.append(list_dict)
print(list01Cnew)
```
**OUTPUT：（確認）同じ中身で辞書からリストに変換することが出来た。**


```:list01Cnewの中身を確認　辞書からリストに変換でけた
[['id',
  '3',
  'survived',
  '1',
  'pclass',
  '1',
  'sex',
  'female',
  'age',
  '35',
  'sibsp',
  '1',
  'parch',
  '0',
  'fare',
  '53.1',
  'embarked',
  'S'],
 ['id',
  '4',
  'survived',
  '0',
  'pclass',
  '3',
  'sex',
  'male',
  'age',
  '35',
  'sibsp',
  '0',
  'parch',
  '0',
  'fare',
  '8.05',
  'embarked',
  'S'],
,
,
,

```
**②作成した「list01Cnew」をCSVに出力する。**

```python
with open(r"dict01C.csv", "w") as f:
    for row in list01Cnew:
        print(*row,sep=',',file = f)
```


**OUTPUT：でけたぁぁあ！！！！　**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/340189/095f3fd0-488b-cc75-ccac-7ffdb626c6c5.png)

最後の「dict01C」のような形の辞書は実務的には使うことがほぼ無いそうです。
今回はループ処理と辞書、リストの変換の練習という意味合いでやってみました。

**以上、タイタニックのトレインデータでデータ型操作のあれこれでした。**

##最後に
**この記事がイイと思ったら、<font color="Blue">イイね</font>、<font color="Blue">フォロー</font>よろしくだってばよ！！！**

**来週もぜってー読んでくれよな！！
きみの瞳に螺旋丸！！！**

**【お詫び】
今回、スペースの都合でお伝え出来なかった
<font color="Red">・家族とタイタニック観た時の気まずい空気を圧倒的に打破する方法</font>
は次回に繰り越しとさせて頂きます。
誠に申し訳ありませんが、皆様のご理解、ご協力のほど宜しくお願い致します。**