【データ解析ライブラリ】Pandas

# Pandasとは
[Pandas -wikipedia](https://ja.wikipedia.org/wiki/Pandas)
>pandasは、プログラミング言語Pythonにおいて、データ解析を支援する機能を提供するライブラリである。
特に、数表および時系列データを操作するためのデータ構造と演算を提供する。
開発者であるWes McKinneyは、財務データを定量分析するための高性能で柔軟なツールを欲しており、AQR Capital Managementにて2008年にpandasの開発を開始した。
 AQRを去る前に上司を説得し、ライブラリの一般公開が可能となった。

## Pandas固有のデータ形式

- 1次元のSeries
- 2次元のDataFrame
    - DataFrameには行名(index)と列名(column)

# DataFrameを作る

## numpyのarrayから作る

```
import numpy as np
import pandas as pd
d = np.array([[1,2,3],[4,5,6],[7,8,9]])
df = pd.DataFrame(d,columns=['a','b','c'])

>>> df
  a b c
0 1 2 3
1 4 5 6
2 7 8 9
```

行名はdf.index
列名はdf.columns
で調べられる

## リスト型を値にもった辞書から作る

```
df = pd.DataFrame({'a':[1,4,7],'b':[2,5,8]},'c':[3,6,9])

>>> df
  a b c
0 1 2 3
1 4 5 6
2 7 8 9
```

# csvファイルを読み込む
```
# 先頭行が列名として扱われる
# index_cols=0 : indexとして使いたい列の列番号を0始まりで指定する

import pandas as pd
df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

print(df.index.values)
# ['Alice' 'Bob' 'Charlie' 'Dave' 'Ellen' 'Frank']

print(df.columns.values)
# ['age' 'state' 'point']
```
## indexがあるcsvは「index_cols=0」を付ける
**index_cols=0**がないとindex列は認識されない。

```
df_header_index = pd.read_csv('data/src/sample_header_index.csv')
print(df_header_index)
#   Unnamed: 0   a   b   c   d
# 0        ONE  11  12  13  14
# 1        TWO  21  22  23  24
# 2      THREE  31  32  33  34
# ========================================================== #
df_header_index_col = pd.read_csv('data/src/sample_header_index.csv', index_col=0)
print(df_header_index_col)
#         a   b   c   d
# ONE    11  12  13  14
# TWO    21  22  23  24
# THREE  31  32  33  34

print(df_header_index_col.index)
# Index(['ONE', 'TWO', 'THREE'], dtype='object')
```
## ヘッダーがないcsvには「header=None」とつける
ヘッダーがないcsvの場合、そのままpd.read_csvすると1行目がcolumnsになってしまう。
**header=None**とすると連番が列名columnsに割り当てられる。
または、**names=('A', 'B', 'C', 'D')**のように列名を設定することもできる。

```
11,12,13,14
21,22,23,24
31,32,33,34

import pandas as pd

df = pd.read_csv('data/src/sample.csv')
print(df)
#    11  12  13  14
# 0  21  22  23  24
# 1  31  32  33  34

print(df.columns)
# Index(['11', '12', '13', '14'], dtype='object')
# ========================================================== #
df_none = pd.read_csv('data/src/sample.csv', header=None)
print(df_none)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34
# ========================================================== #
df_names = pd.read_csv('data/src/sample.csv', names=('A', 'B', 'C', 'D'))
print(df_names)
#     A   B   C   D
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34
```

## 列を指定して読み込むときは「usecols」を使う
```
df_none_usecols = pd.read_csv('data/src/sample.csv', header=None, usecols=[1, 3])
print(df_none_usecols)
#     1   3
# 0  12  14
# 1  22  24
# 2  32  34
# ========================================================== #
df_header_usecols = pd.read_csv('data/src/sample_header.csv',
                                usecols=lambda x: x is not 'b')
print(df_header_usecols)
#     a   c   d
# 0  11  13  14
# 1  21  23  24
# 2  31  33  34
# ========================================================== #
df_index_usecols = pd.read_csv('data/src/sample_header_index.csv',
                               index_col=0, usecols=[0, 1, 3])
print(df_index_usecols)
#         a   c
# ONE    11  13
# TWO    21  23
# THREE  31  33
```

## 行をスキップしたいときは「skiprows」を使う
skiprowsに整数を渡すと、**ファイルの先頭をその行数分スキップ**して読み込む。

```
df_none = pd.read_csv('data/src/sample.csv', header=None)
print(df_none)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34
# ========================================================== #
df_none = pd.read_csv('data/src/sample.csv', header=None, skiprows=2)
print(df_none)
#     0   1   2   3
# 0  31  32  33  34
# ========================================================== #
df_none_skiprows = pd.read_csv('data/src/sample.csv', header=None, skiprows=[1])
print(df_none_skiprows)
#     0   1   2   3
# 0  11  12  13  14
# 1  31  32  33  34
# ========================================================== #
# 最後の行をスキップする場合は「skipfooter=1」に設定
# engine='python'を指定しないとWarningが出る可能性がある
df_none_skipfooter = pd.read_csv('data/src/sample.csv', header=None,
                                 skipfooter=1, engine='python')
print(df_none_skipfooter)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24
```

## 読みたい行数は「nrows」で指定する
```
df_none_nrows = pd.read_csv('data/src/sample.csv', header=None, nrows=2)
print(df_none_nrows)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24
```

## 列の型を指定するときは「dtype」を使う
```
df_str_col = pd.read_csv('data/src/sample_header_index_dtype.csv',
                         index_col=0, dtype={'b': str, 'c': str})
print(df_str_col)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_str_col.dtypes)
# a     int64
# b    object
# c    object
# d    object
# dtype: object
# ========================================================== #
# DataFrameの列は「astype」で型変換できる
print(df['s_i'].astype(int))
# 0      0
# 1     10
# 2    200
# Name: s_i, dtype: int64

```

# 欠損値
>By default the following values are interpreted as NaN: ‘’, ‘#N/A’, ‘#N/A N/A’, ‘#NA’, ‘-1.#IND’, ‘-1.#QNAN’, ‘-NaN’, ‘-nan’, ‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘n/a’, ‘nan’, ‘null’.
pandas.read_csv — pandas 0.23.0 documentation

## 欠損値として扱う値を追加するときは「na_values」
```
df_nan = pd.read_csv('data/src/sample_header_index_nan.csv', index_col=0)
print(df_nan)
#          a   b
# ONE    NaN NaN
# TWO      - NaN
# THREE  NaN NaN
# ========================================================== #
df_nan_set_na = pd.read_csv('data/src/sample_header_index_nan.csv',
                            index_col=0, na_values='-')
print(df_nan_set_na)
#         a   b
# ONE   NaN NaN
# TWO   NaN NaN
# THREE NaN NaN
```

## 欠損値を自分で決めたいときは「na_values」と「keep_default_na=False」を一緒に使う
```
,a,b
ONE,,NaN
TWO,-,nan
THREE,null,N/A
# ========================================================== #
df_nan_set_na_no_keep = pd.read_csv('data/src/sample_header_index_nan.csv',
                                    index_col=0, na_values=['-', 'NaN', 'null'],
                                    keep_default_na=False)
print(df_nan_set_na_no_keep)
#          a    b
# ONE         NaN
# TWO    NaN  nan
# THREE  NaN  N/A
```

## 欠損値をなくすときは「na_filter」を使う
```
,a,b
ONE,,NaN
TWO,-,nan
THREE,null,N/A
# ========================================================== #
df_nan_no_filter = pd.read_csv('data/src/sample_header_index_nan.csv',
                               index_col=0, na_filter=False)
print(df_nan_no_filter)
#           a    b
# ONE          NaN
# TWO       -  nan
# THREE  null  N/A
```

## データに日本語が含まれているときは「encoding='shift_jis'」を使う
```
df_sjis = pd.read_csv('data/src/sample_header_shift_jis.csv',
                      encoding='shift_jis')
print(df_sjis)
#    a   b   c   d
# 0  あ  12  13  14
# 1  い  22  23  24
# 2  う  32  33  34
```

## なんでも読めちゃうread_csvは本当に優秀…
>拡張子が.gz, .bz2, .zip, .xzの場合、自動で検出して展開してくれる。拡張子が異なる場合、引数compressionに文字列'gz', 'bz2', 'zip', 'xz'を明示的に指定する。
なお、対応しているのはcsvファイル単体が圧縮されている場合のみ。複数ファイルが圧縮されている場合はエラーになる。
zipとxzはバージョン0.18.1からの対応。

```
df_zip = pd.read_csv('data/src/sample_header.csv.zip')
df_web = pd.read_csv('http://www.post.japanpost.jp/zipcode/dl/oogaki/zip/13tokyo.zip',
                 header=None, encoding='shift_jis')
```

# 新しい列を作る
```
# 水平方向(axis = 1) に総和をとり、Total という列を作る
df['Total'] = df.sum(axis=1)
```

# 要約統計量
at, iat : 単独の要素の値を選択、取得・変更
loc, iloc : 単独および複数の要素の値を選択、取得・変更
>count: 要素の個数
unique: ユニークな（一意な）値の要素の個数
top: 最頻値（mode）
freq: 最頻値の頻度（出現回数）
mean: 算術平均
std: 標準偏差
min: 最小値
max: 最大値
50%: 中央値（median）
25%, 75%: 1/4分位数、3/4分位数

```
import pandas as pd

df = pd.DataFrame({'a': [1, 2, 1, 3],
                   'b': [0.4, 1.1, 0.1, 0.8],
                   'c': ['X', 'Y', 'X', 'Z'],
                   'd': ['3', '5', '2', '1'],
                   'e': [True, True, False, True]})

print(df)
#    a    b  c  d      e
# 0  1  0.4  X  3   True
# 1  2  1.1  Y  5   True
# 2  1  0.1  X  2  False
# 3  3  0.8  Z  1   True

print(df.dtypes)
# a      int64
# b    float64
# c     object
# d     object
# e       bool
# dtype: object
# ========================================================== #
## データフレーム df の要約統計量を表示
# 各列ごとの平均や標準偏差、最大値、最小値、最頻値など

print(df.describe())
#               a         b
# count  4.000000  4.000000
# mean   1.750000  0.600000
# std    0.957427  0.439697
# min    1.000000  0.100000
# 25%    1.000000  0.325000
# 50%    1.500000  0.600000
# 75%    2.250000  0.875000
# max    3.000000  1.100000

print(type(df.describe()))
# <class 'pandas.core.frame.DataFrame'>

print(df.describe().loc['std']) # stdは標準偏差
# a    0.957427
# b    0.439697
# Name: std, dtype: float64

print(df.describe().at['std', 'b'])
# 0.439696865275764
```

## 文字列など数値以外の列の結果を表示したいときは「exclude='number'」を使う
**include='all'とすると、すべての型の列が対象となる。**

```
print(df.describe(exclude='number'))
#         c  d     e
# count   4  4     4
# unique  3  4     2
# top     X  3  True
# freq    2  1     3
```

# データのプロット
```
df.plot() #折れ線グラフ
df.plot.bar(stacked=True) # 積み上げ棒グラフ
df.plot.scatter(‘Japanese’,’English’) # 列を指定して散布図
df[‘Japanese’].plot.hist() # 列を指定してヒストグラム
```