【Python】10分で完全に理解するpandas

# 10分で分かるpandas
## はじめに
この記事はpandas公式チュートリアル「10 minutes to pandas」の写経及び解説です

以下のURLを参考にしています
https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html

## 環境
- Python3.7
- Jupyter Lab

## とりあえずインポート
```
import numpy as np
import pandas as pd
np
pd
```

以下のように各モジュールが表示されればOK
<img width="651" alt="スクリーンショット 2020-01-25 11.51.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/ae83854a-25f5-7a45-4b91-1e7b239c4b9c.png">

### エラーが起きた場合
**ModuleNotFoundError: No module named 'pandas'**と怒られる場合、まずpandasを入れます。

```

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-59ab05e21164> in <module>
      1 import numpy as np
----> 2 import pandas as pd

ModuleNotFoundError: No module named 'pandas'

```

コマンド
`python -m pip install pandas`

---

## [1. オブジェクトを作る](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#object-creation)

[Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html#pandas.Series)クラスにリストを入れることで簡単にデータを作ることが出来ます。

```py

# 簡単に一列作る
s = pd.Series(data=[1, 3, 5, np.nan, 6, 8])
s
```
<img width="642" alt="スクリーンショット 2020-01-25 12.05.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/16930c2e-cad0-b69b-3ad5-dd8df557af88.png">



[date_range()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.date_range.html)を使うことで、特定の期間の日付の行を作成出来ます。

```py

# 2020年1月１日から6日間のデータ
dates = pd.date_range("20200101", periods=6)
dates
```
<img width="643" alt="スクリーンショット 2020-01-25 12.14.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/80a64cbb-ef3f-e0d6-f1ce-8c94b1655924.png">




pandasの[DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html#pandas-dataframe)クラス**引数index**を指定することで、行インデックスを指定することが出来ます。


```py
# 行インデックスに2020年1月1日からのデータを指定
# 各値にはランダムな数値を入れる
df = pd.DataFrame(np.random.randn(6, 4), index=dates)
df
```
<img width="648" alt="スクリーンショット 2020-01-25 12.20.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/7d54847d-d63f-bb8b-93f4-b116eea0fd76.png">

また、同じくDataFrameクラスの
**引数columns**を指定することで列名を設定することが出来ます。

```py
# 列名ABCDを設定
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD"))
df
```
<img width="683" alt="スクリーンショット 2020-01-25 13.54.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/b30003b8-8011-2ef5-9d1e-72e3aeb4e2c6.png">



DataFrameクラスに辞書型のデータを渡すことで、辞書型のキーの部分が列名になります。

```py
df2 = pd.DataFrame(
    {
        "A": 1.,
        "B": pd.Timestamp("20200101"),
        "C": pd.Series(1, index=list(range(4)), dtype="float32"),
        "D": np.array([3] * 4, dtype="int32"),
        "E": pd.Categorical(["test", "train", "test", "train"]),
        "F": "foo",
    }
)
df2
```
<img width="888" alt="スクリーンショット 2020-01-25 14.08.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/ec976e0a-6ddc-a8da-5d15-7dec6fa81695.png">

**dtypes属性**に参照することで各列のデータ属性が分かります。

```py
df2.dtypes
```
<img width="854" alt="スクリーンショット 2020-01-25 14.10.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/8c7f2c4a-f1d5-b584-2307-727417fd414d.png">


Jupyter nootbookやJupyter Labなどを使っている場合、列名がタブ補完で表示されます。

```
db2.<TAB>
```
<img width="863" alt="スクリーンショット 2020-01-25 14.13.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/4c87ffbb-5c93-1ac2-b7a2-184d8b891e85.png">

## [2. データを表示する](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#object-creation)

DataFrameクラスの[head()メソッド](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.head.html#pandas.DataFrame.head)を使うことでデータの先頭部を表示できます。

```py
df.head(2)
```

<img width="853" alt="スクリーンショット 2020-01-25 14.21.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/d0f0d698-8f58-272c-cf13-6411870bfbab.png">




同じくDataFrameクラスの[tail()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.tail.html#pandas-dataframe-tail)を使うことでデータの後尾部を表示できます。

```py
df.tail(2)
```

<img width="859" alt="スクリーンショット 2020-01-25 14.35.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/a8b7b52f-e33a-5da0-9f2c-b2ba6af7bc22.png">


DataFrameクラスの**[index](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.index.html#pandas-dataframe-index)**を参照することでそのデータの行インデックスを表示出来ます。

```py
df.index
df2.index
```

<img width="857" alt="スクリーンショット 2020-01-25 14.36.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/6ead009a-2469-561a-955c-0b865ca52412.png">


DataFrameクラスの[to_numpy()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_numpy.html#pandas-dataframe-to-numpy)を使うことでデータをnumpyで操作しやすいデータに変換できます。

```py
df.to_numpy()
df2.to_numpy()
```
<img width="860" alt="スクリーンショット 2020-01-25 15.25.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/ecd8f5ee-9b88-63be-7ae3-242a57d40c85.png">


DataFrameクラスの[参考：DataFrame.describe()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.describe.html#pandas-dataframe-describe)を使うことで、データの各列の簡単な統計を取ることができます。

```py
df2.describe()
```
<img width="863" alt="スクリーンショット 2020-01-25 15.44.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/e687573a-b407-b255-4107-2b2a5d063e1a.png">


DataFrameクラスの[T属性](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.T.html#pandas-dataframe-t)を参照すると、行列入れ替えたデータにアクセスできます。

```py
df.T
```
<img width="856" alt="スクリーンショット 2020-01-25 15.48.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/84c69ff0-2dd4-e37d-ec1f-daa729c1aa1e.png">

また、DataFrameクラスの[transpose()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.transpose.html#pandas-dataframe-transpose)でも同じく行列の入れ替えを取得できます。

```py
df.transpose()
```

<img width="858" alt="スクリーンショット 2020-01-25 16.00.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/d01e6e94-53f7-8e13-1aae-e36d1bcd7882.png">

DataFrameクラスの[sort_index()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_index.html#pandas-dataframe-sort-index)を使用することで、行全体もしくは列全体の並び替えを行うことができます。

```py
df.sort_index()
```
<img width="864" alt="スクリーンショット 2020-01-25 16.10.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/6e5c2281-5d39-ecd6-dec8-3d3a28ca8e0b.png">

**引数axis**に0もしくは"index"を設定すると行に、1もしくは"columns"を設定すると、列を軸に並び替えします(デフォルト値0)。また、**引数ascending**にFalseを指定すると並び順が降順になります(デフォルト値True)。

```py

df.sort_index(axis=0, ascending=False)
df.sort_index(axis=1, ascending=False)
```
<img width="869" alt="スクリーンショット 2020-01-25 16.12.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/60398e1c-69a0-67b5-00dc-8513ac05a088.png">

DataFrameクラスの[sort_values()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html#pandas-dataframe-sort-values)を使用することで行単位もしくは列単位に並び替えを行うことができます。

```py
df.sort_values(by="B")
df.sort_values(by="2020-01-01", axis=1)
```
<img width="445" alt="スクリーンショット 2020-01-25 16.45.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/fd9dc57d-108d-9066-3d7f-653483e5fdf1.png">


（2020-03-07追記）


## [3. データを選択する](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#selection)
### [単純なデータ取得](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#getting)

**df["A"]**もしくは**df.A**とすることで、指定した一列を取得することができます。

```py
df["A"]
df.A
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/e39b695c-aa86-c9e5-ee34-47709418b841.png)

リスト**[]**で指定した場合、Pythonのスライス操作で列や行を選択することができます

```py
# 先頭4列表示
df[0:3]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/0c39cfad-4875-f554-beab-65f368e72eab.png)

リインデックスの範囲を取得することもできます。

```py

# 2020年1月2日から2020年1月4日まで表示
df['20200102':'20200104'] 
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/fa23ca4c-84f8-13db-73d0-cafecfaee512.png)


### [ラベルを指定してデータを選択する](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#selection-by-label)

DataFrameクラスの[loc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html#pandas-dataframe-loc)にインデックス(今回の場合dates)を指定することで、行を列として選択することができます。

```py

df.loc[dates]
df.loc[dates[0]]

```



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/ea80f2f5-60d6-c5db-0c61-d8298a1dfdf3.png)

[loc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html#pandas-dataframe-loc)を使うことで、複数列を選択することができます。


```py

df.loc[:, ["A", "B"]]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/9533685b-bf0e-a081-ddc7-a3d123049d71.png)

先頭のコロンがない場合エラーになるみたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/08640c4b-104b-d5f0-8f0d-aaa64c1d1bcc.png)


[loc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html#pandas-dataframe-loc)スライス操作を組み合わせることで複数行、複数列選択することができます。

```py
df.loc['20200102':'20200104', ['A', 'B']]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/4e66af2c-f86f-1509-265a-435e637803a3.png)

[loc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html#pandas-dataframe-loc)にインデックスを指定することで単体データを取得できます

```py
df.loc[dates[0], 'A']
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/00d3a74c-7fa8-013a-8508-39d3d49a71c7.png)

[at()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.at.html)を使うことでより高速に単体データを取得することができます

```py
df.at[dates[0], 'A']
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/4d1641fb-0c89-9ed1-1db5-064c024c5c40.png)

### [位置を指定してデータを選択する](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#selection-by-position)

DataFrameクラスの[iloc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html)を使うことで、数値を指定してデータ選択することが出来ます。

```py
df.iloc[3]
df.iloc[3:5, 0:2]
df.iloc[[1, 2, 4], [0, 2]]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/2df2fb73-ba55-22a2-46ab-d10a6ae160f4.png)

DataFrameクラスの[iloc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html)の引数に開始位置終了位置を省略したスライス(:のみ)を指定することで、特定の全行 or 全列を取得できます

```py
df.iloc[1:3, :]
df.iloc[:, 1:3]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/15b3033b-5a52-9c64-fdd1-e0edb466ccc6.png)

DataFrameクラスの[iloc()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html)に引数にを数値のみ指定することで、単体データの選択ができます

```py
df.iloc[1, 1]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/4a16cd60-228b-1d53-377a-651a0948dbd9.png)


[at()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.at.html)と同様、[iat()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iat.html)使うことでより高速に単体データを取得することができます

```py
df.at[dates[0], 'A']
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290735/33b2f98c-143f-df68-d6b5-d5c8c016817a.png)

### [条件判定によるデータ選択](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#boolean-indexing)

 （ここで力尽きる。残り……多くない？10分とは:thinking: ）

[4. 欠損データ](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#missing-data)
[5. 操作](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#operations)
[6. マージ](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#merge)
[7. グルーピング](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#grouping)
[8. 再構築](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#reshaping)
[9. 時系列](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#time-series)
[10. カテゴリー化](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#categoricals)
[11. プロット](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#plotting)
[12. データの入力と出力](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#getting-data-in-out)
[13. 落とし穴](https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#gotchas)