Pandas入門


## ・Pandas入門
今現在、プロジェクトでPythonのライブラリ「Pandas」を使っているので、覚書も含め纏めたいと思います。
不備などありましたら、ご指摘をお願い致します。
## ・Pandasとは
Pandasとはデータ解析、操作を迅速で快適かつ簡単に行なうことができるPythonで作られたオープンソースライブラリになります。
開発者であるWes McKinneyは、財務データを定量分析するための高性能で柔軟なツールを欲しており、AQR Capital Managementにて2008年にpandasの開発を開始した。 AQRを去る前に上司を説得し、ライブラリの一般公開が可能となった。
別のAQR従業員であるChang Sheは、2012年からこのライブラリの２番目の主要コントリビューターとなった。同時期に、Pythonコミュニティでライブラリが普及し、さらに多くのコントリビューターがプロジェクトに加わることになった。
2015年、pandasはNumFOCUS（アメリカ合衆国における501(c)(3)非営利慈善団体）の財政出資プロジェクトとして署名した。

## ・Pandasのインストール

```python
pip install pandas
```

## ・使い方
Pandasを利用するには通例、以下のようにPandasライブラリを読み込みます。

```python
import pandas as pd
```

## ・Pandasのデータ構造
Pandasでは1次元配列のSeries、2次元配列のDataframe、3次元配列のPanelが用意されています。
今回はよく利用するSeries、Dataframeについてまとめていきます。

## ・Series生成
Seriesの生成は以下のようになります。

```python
pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
```

## 各パラメータの説明

|引数| 内容|
|-|-|
|・data|データ：配列相当のもの、ディクショナリ、数値<br>データがディクショナリの場合には引数の順序は維持されます。|
|・index| データ：配列相当のもの、または1次元配列のインデックス。<br>デフォルトとしてRangeIndexが0から1, 2, …, nの順番で設定される。ディクショナリ相当のデータでインデックスが指定されていない場合、キーがインデックスとして使用される。|
|・dtype| データ：str型、numpy.dtype、ExtensionDtype<br>出力されるSeriesのデータ型を指定したい場合に設定。Noneの場合は型推論で指定される。|
|・name|データ：str型<br>Seriesの列名を設定|
|・copy|データ：bool型 デフォルト：False<br>入力されたデータの参照を利用するか、コピーを利用するかを指定。|

```python
pd.Series(["name1","name2","name3"])
```
|index|col1|
|-|-|
|0|name1|
|1|name2|
|2|name3|
dtype: object

## ・DataFrame生成
DataFrameの生成は以下のようになります。

```python
pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)
```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951135/fcfbd506-5093-d46a-b90e-179fcbe2ffd4.png)

各パラメータの説明

|引数| 内容|
|-|-|
|・data|データ：ndarray、Iterable、ディクショナリ、DataFrame<br>ディクショナリにはSeries、配列、定数、dataclass、リスト相当のオブジェクトを含めれます。データがディクショナリの場合、列の順番は挿入の順番に準拠します。|
|・index|データ：インデックスまたは配列相当のもの<br>インデックスを配列などで指定。インデックスを指定していない場合は、デフォルトとしてRangeIndexが0から1, 2, …, nの順番で設定される。|
|・columns|データ：インデックスまたは配列相当のもの<br>データにカラム名がない場合、結果にカラム名を設定。デフォルトとしてRangeIndexが0から1, 2, …, nの順番で設定される。|
|・dtype|データ：dtype デフォルト None<br>出力されるDataframeのデータ型を指定したい場合に設定。Noneの場合は型推論で指定される。|
|・copy|データ：bool型 デフォルト：None<br>入力データのコピー。<br>ディクショナリのデフォルトの設定はNoneでcopy=Trueの振る舞いをする。データフレーム、二次元配列のデータのデフォルトの設定はNoneでcopy=Falseの振る舞いをする。version 1.3.0.で変更されているようです。|

```python
data_list = [["name1", "address1", "M", pd.Timestamp("20000101"), 170.0, 60.0],["name2", "address2", "F", pd.Timestamp("20000102"), 160.0, 50.0],["name3", "address3", "M", pd.Timestamp("20000103"), 180.0, 70.0]]
df = pd.DataFrame(data_list, columns=["col1", "col2", "col3", "col4", "col5", "col6"])
```

|index|col1|col2 |col3|col4|col5|col6|
|-|-|-|-|-|-|-|
|0|name1|address1|M|2000-01-01|170.0|60.0|
|1|name2|address2|F|2000-01-02|160.0|50.0|
|2|name3|address3|M|2000-01-03|180.0|70.0|

## ・列データの追加

```python
new_data_list = [1,2,1]
df["col7"] = new_data_list
```
|index|col1|col2 |col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|
|0|name1|address1|M|2000-01-01|170.0|60.0|1|
|1|name2|address2|F|2000-01-02|160.0|50.0|2|
|2|name3|address3|M|2000-01-03|180.0|70.0|1|

## 要素の選択
列を指定した取得方法（二つは同一結果）

```python
df["col1"]
```
|index|col1|
|-|-|
|0|name1|
|1|name2|
|2|name3|
Name: col1, dtype: object

```python
df.col1
```
|index|col1|
|-|-|
|0|name1|
|1|name2|
|2|name3|
Name: col1, dtype: object

行を指定した取得方法

```python
df[0:2]
```
|index|col1|col2 |col3|col4|col5|col6|
|-|-|-|-|-|-|-|
|0|name1|address1|M|2000-01-01|170.0|60.0|
|1|name2|address2|F|2000-01-02|160.0|50.0|

数値で位置を指定した行の取得方法

```python
df.iloc[2]
```
|Name|Value|
|-|-|
|col1|name3|
|col2|address3|
|col3|M|
|col4|2000-01-0300:00:00|
|col5|180|
|col6|70|
Name: 2, dtype: object

行および列を数値位置で指定しての取得方法。

```python
df.iloc[[0, 2], [0, 2]]
```
|index|col1|col3|
|-|-|-|
|0|name1|M|
|2|name3|M|

行を指定しての取得方法

```python
df.iloc[[0,2], :]
```
|index|col1|col2|col3|col4|col5|col6|
|-|-|-|-|-|-|-|-|
|0|name1|address1|M|2000-01-01|170.0|60.0|
|2|name3|address3|M|2000-01-03|180.0|70.0|

Boolean indexing

```python
df[df["col5"] > 160]
```
|index|col1|col2|col3|col4|col5|col6|
|-|-|-|-|-|-|-|-|
|0|name1|address1|M|2000-01-01|170.0|60.0|

```python
df[df["col6"].isin([50.0, 70.0])]
```
|index|col1|col2|col3|col4|col5|col6|
|-|-|-|-|-|-|-|-|
|1|name2|address2|F|2000-01-02|160.0|50.0|
|2|name3|address3|M|2000-01-03|180.0|70.0|

## ・グループ化
データ

```python
data_list = [["name1", "address1", "M", pd.Timestamp("20000101"), 170.0, 60.0,1],["name2", "address2", "F", pd.Timestamp("20000102"), 160.0, 50.0,2],["name3", "address3", "M", pd.Timestamp("20000103"), 180.0, 70.0,1],["name4", "address4", "F", pd.Timestamp("20000104"), 150.0, 40.0,1],["name5", "address5", "M", pd.Timestamp("20000105"), 190.0, 80.0,2],["name6", "address6", "M", pd.Timestamp("20000106"), 200.0, 90.0,1],["name7", "address7", "F", pd.Timestamp("20000107"), 140.0, 40.0,1],["name8", "address8", "F", pd.Timestamp("20000108"), 150.0, 50.0,2],["name9", "address9", "F", pd.Timestamp("20000109"), 170.0, 60.0,1],["name10", "address10", "M", pd.Timestamp("20000110"), 170.0, 60.0,2]]
df = pd.DataFrame(data_list, columns=["col1", "col2", "col3", "col4", "col5", "col6", "col7"])
```
|index|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|0|name1|address1|M|2000-01-01|170.0|60.0|1|
|1|name2|address2|F|2000-01-02|160.0|50.0|2|
|2|name3|address3|M|2000-01-03|180.0|70.0|1|
|3|name4|address4|F|2000-01-04|150.0|40.0|1|
|4|name5|address5|M|2000-01-05|190.0|80.0|2|
|5|name6|address6|M|2000-01-06|200.0|90.0|1|
|6|name7|address7|F|2000-01-07|140.0|40.0|1|
|7|name8|address8|F|2000-01-08|150.0|50.0|2|
|8|name9|address9|F|2000-01-09|170.0|60.0|1|
|9|name10|address10|M|2000-01-10|170.0|60.0|2|

列を指定してグループ化した結果を取得する方法。

```python
gp_df = df.groupby("col3")
df.loc[gp_df['col5'].idxmax(),:]
```

|index|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|8|name9|address9|F|2000-01-09|170.0|60.0|1|
|5|name6|address6|M|2000-01-06|200.0|90.0|1|

複数列を指定してグループ化した結果を取得する方法。

```python
gp_df = df.groupby(["col3","col7"])
df.loc[gp_df['col5'].idxmax(),:]
```
|index|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|8|name9|address9|F|2000-01-09|170.0|60.0|1|
|1|name2|address2|F|2000-01-02|160.0|50.0|2|
|5|name6|address6|M|2000-01-06|200.0|90.0|1|
|4|name5|address5|M|2000-01-05|190.0|80.0|2|

## ・マージ処理


## concat
縦方向に単純に結合する方法。
データ1

```python
data_list = [["101","name1", "address1", "M", pd.Timestamp("20000101"), 170.0, 60.0,1],["102","name2", "address2", "F", pd.Timestamp("20000102"), 160.0, 50.0,2],["103","name3", "address3", "M", pd.Timestamp("20000103"), 180.0, 70.0,1],["104","name4", "address4", "F", pd.Timestamp("20000104"), 150.0, 40.0,1],["105","name5", "address5", "M", pd.Timestamp("20000105"), 190.0, 80.0,2]]
df = pd.DataFrame(data_list, columns=["ID","col1", "col2", "col3", "col4", "col5", "col6", "col7"])
```
|index|ID|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|0|101|name1|address1|M|2000-01-01|170.0|60.0|1|
|1|102|name2|address2|F|2000-01-02|160.0|50.0|2|
|2|103|name3|address3|M|2000-01-03|180.0|70.0|1|
|3|104|name4|address4|F|2000-01-04|150.0|40.0|1|
|4|105|name5|address5|M|2000-01-05|190.0|80.0|2|

データ2

```python
data_list2 = [["106","name6", "address6", "M", pd.Timestamp("20000106"), 200.0, 90.0,1],["107","name7", "address7", "F", pd.Timestamp("20000107"), 140.0, 40.0,1],["108","name8", "address8", "F", pd.Timestamp("20000108"), 150.0, 50.0,2],["109","name9", "address9", "F", pd.Timestamp("20000109"), 170.0, 60.0,1],["110","name10", "address10", "M", pd.Timestamp("20000110"), 170.0, 60.0,2]]
df2 = pd.DataFrame(data_list2, columns=["ID","col1", "col2", "col3", "col4", "col5", "col6", "col7"])
```

|index|ID|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|0|106|name6|address6|M|2000-01-06|200.0|90.0|1|
|1|107|name7|address7|F|2000-01-07|140.0|40.0|1|
|2|108|name8|address8|F|2000-01-08|150.0|50.0|2|
|3|109|name9|address9|F|2000-01-09|170.0|60.0|1|
|4|110|name10|address10|M|2000-01-10|170.0|60.0|2|

結合結果

```python
pd.concat([df,df2],ignore_index=True)
```
|index|ID|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|0|101|name1|address1|M|2000-01-01|170.0|60.0|1|
|1|102|name2|address2|F|2000-01-02|160.0|50.0|2|
|2|103|name3|address3|M|2000-01-03|180.0|70.0|1|
|3|104|name4|address4|F|2000-01-04|150.0|40.0|1|
|4|105|name5|address5|M|2000-01-05|190.0|80.0|2|
|5|106|name6|address6|M|2000-01-06|200.0|90.0|1|
|6|107|name7|address7|F|2000-01-07|140.0|40.0|1|
|7|108|name8|address8|F|2000-01-08|150.0|50.0|2|
|8|109|name9|address9|F|2000-01-09|170.0|60.0|1|
|9|110|name10|address10|M|2000-01-10|170.0|60.0|2|

## merge
横方向に結合する方法。

データ3

```python
data_list = [["101","name1", "address1", "M", pd.Timestamp("20000101"), 170.0, 60.0,1],["102","name2", "address2", "F", pd.Timestamp("20000102"), 160.0, 50.0,2],["104","name4", "address4", "F", pd.Timestamp("20000104"), 150.0, 40.0,1],["105","name5", "address5", "M", pd.Timestamp("20000105"), 190.0, 80.0,2],["106","name6", "address6", "M", pd.Timestamp("20000106"), 200.0, 90.0,1],["107","name7", "address7", "F", pd.Timestamp("20000107"), 140.0, 40.0,1],["110","name10", "address10", "M", pd.Timestamp("20000110"), 170.0, 60.0,2]]
df = pd.DataFrame(data_list, columns=["ID","col1", "col2", "col3", "col4", "col5", "col6", "col7"])
```

|index|ID|col1|col2|col3|col4|col5|col6|col7|
|-|-|-|-|-|-|-|-|-|
|0|101|name1|address1|M|2000-01-01|170.0|60.0|1|
|1|102|name2|address2|F|2000-01-02|160.0|50.0|2|
|2|104|name4|address4|F|2000-01-04|150.0|40.0|1|
|3|105|name5|address5|M|2000-01-05|190.0|80.0|2|
|4|106|name6|address6|M|2000-01-06|200.0|90.0|1|
|5|107|name7|address7|F|2000-01-07|140.0|40.0|1|
|6|110|name10|address10|M|2000-01-10|170.0|60.0|2|

データ4

```python
data_list2 = [["101",100,10,50],["102",90,20,60],["103",80,30,70],["105",60,50,90],["106",50,60,100],["108",30,80,20],["109",20,90,30]]
df2 = pd.DataFrame(data_list2, columns=["ID","science","english","math"])
```

|index|ID|science|english|math|
|-|-|-|-|-|
|0|101|100|10|50|
|1|102|90|20|60|
|2|103|80|30|70|
|3|105|60|50|90|
|4|106|50|60|100|
|5|108|30|80|20|
|6|109|20|90|30|

## INNER JOINでの結合方法
```python
pd.merge(df,df2,how="inner",on="ID")
```

結合結果

|index|ID|col1|col2|col3|col4|col5|col6|col7|science|english|math|
|-|-|-|-|-|-|-|-|-|-|-|-|
|0|101|name1|address1|M|2000-01-01|170.0|60.0|1|100|10|50|
|1|102|name2|address2|F|2000-01-02|160.0|50.0|2|90|20|60|
|2|105|name5|address5|M|2000-01-05|190.0|80.0|2|60|50|90|
|3|106|name6|address6|M|2000-01-06|200.0|90.0|1|50|60|100|

## LEFT JOINでの結合方法

```python
pd.merge(df,df2,how="left",on="ID")
```

結合結果

|index|ID|col1|col2|col3|col4|col5|col6|col7|science|english|math|
|-|-|--|-|-|-|-|-|-|-|-|-|
|0|101|name1|address1|M|2000-01-01|170.0|60.0|1|100.0|10.0|50.0|
|1|102|name2|address2|F|2000-01-02|160.0|50.0|2|90.0|20.0|60.0|
|2|104|name4|address4|F|2000-01-04|150.0|40.0|1|NaN|NaN|NaN|
|3|105|name5|address5|M|2000-01-05|190.0|80.0|2|60.0|50.0|90.0|
|4|106|name6|address6|M|2000-01-06|200.0|90.0|1|50.0|60.0|100.0|
|5|107|name7|address7|F|2000-01-07|140.0|40.0|1|NaN|NaN|NaN|
|6|110|name10|address10|M2000-01-10|170.0|60.0|2|NaN|NaN|NaN|

## RIGHT JOINでの結合方法

```python
pd.merge(df,df2,how="right",on="ID")
```

結合結果

|index|col1|col2 |col3|col4|col5|col6|col7| science | english | math |
|-|-|-|-|-|-|-|-|-|-|-|
|0|101|name1|address1|M|2000-01-01|170.0|60.0|1.0|100|10|50|
|1|102|name2|address2|F|2000-01-02|160.0|50.0|2.0| 90|20|60|
|2|105|name5|address5|M|2000-01-05|190.0|80.0|2.0|60|50|90|
|3|106|name6|address6|M|2000-01-06|200.0|90.0|1.0|50|60|100|
|4|103|NaN|NaN|NaN|NaT|NaN|NaN|NaN|80|30|70|
|5|108|NaN|NaN|NaN|NaT|NaN| NaN|NaN|30|80|20|
|6|109|NaN|NaN|NaN|NaT|NaN|NaN|NaN|20|90|30|



## ・データの入出力
CSVデータの入出力方法

```python
df.to_csv("foo.csv")
pd.read_csv("foo.csv")
```
Excelデータの入出力方法

```python
df.to_excel("foo.xlsx", sheet_name="Sheet1")
pd.read_excel("foo.xlsx", "Sheet1", index_col=None, na_values=["NA"])
```

##  まとめ
基本的なpandasの使い方をまとめました。
pandasは他にも色々便利な機能も用意されているので、今後利用した際にまとめたいと思います。

## 参考資料
https://pandas.pydata.org/docs/index.html