pandasの基本(使い方メモ)

# Pandasとは
データ解析を支援する機能を持つPythonのオープンソースライブラリ

### Pandas DataFrame
* データを行列で保存
* 2次元のデータで値，インデックス，列で構成
* 要素には数値だけでなく文字列を入れることも可能

### Pandas Series
* 1次元の配列としてデータを扱う 
* 要素には数値だけでなく文字列を入れることも可能

##使い方

###データの変換方法
* import pandas as pd Pandasをpdとしてインポート
* DataFrame.columns データフレームのカラム情報
* DataFrame.index データフレームのインデックス情報

```python

import numpy as np
import pandas as pd

body = np.array([[120,21,32],[12,213,32]])
# DataFrameに変換
df = pd.DataFrame(body)
# カラム名を変更
df.columns = ['naka', 'yama', 'hayate']
# 行名を変更
df.index = ['day1','day2']
# 列名をrename(nakaからhogeに)
df = df.rename(columns={'naka':'hoge'})
```

###データ構造の確認
* pd.DataFrame() データフレームの作成
* DataFrame.index データフレームのインデックス情報
* DataFrame.shape データフレームのサイズ（行列のサイズ）
* DataFrame.describe() 基本統計量の確認
* DataFrame.astype() dtype（データ型）の指定
* DataFrame.info() データフレームのサマリー（要約情報）
* DataFrame['A'] 列「A」の要素
* DataFrame.A 同様に列「A」の要素
* DataFrame.loc[:, ['A']] 全ての行の列「A」の要素
* DataFrame.loc['Math',['A','C']] 行「Math」と列「A」「C」の要素
* DataFrame.iloc[0] 行「0」の要素
* DataFrame.iloc[1] 行「1」の要素
* DataFrame.iloc[:, 0:3] 全ての行の列「0〜3」までの要素
* DataFrame.iloc[0, 0:4] 行「０」の列「0〜4」までの要素
* locとilocは混乱しがちですので間違えなく覚えましょう
* locはラベル名を指定、ilocは行列番号を指定

```python

#データ構造の確認
df = pd.DataFrame(data=[['10','29','49'],['20','33','44']], columns=['A','B','C'])
df.index = ['Eng', 'Spa']
#データの前後5行ずつ
df.head()
df.tail()
#行列のサイズ
df.shape
#行列のinfo
df.info()
#データ形式の変更
df = df.astype(int)
#データの基本統計量
df.describe()
#データの各要素へのアクセス
df['A']
df.A
type(df['A']) # pandas.core.series.Series（シリーズ）

#行，列名で選択(loc)
#column名で指定
df.loc[:,['A']]
#index名で指定
df.loc['Eng', ['A','C']]

#行，列名で選択(iloc)
df.iloc[0]
#iloc[行,[列]]
df.iloc[0,[0,2]]
df.iloc[1,0:2]
```

###CSVデータの読み込み
* pd.read_csv() CSVデータからデータフレームの作成
* DataFrame.head() データフレームの最初の5行を表示（デフォルト）
* DataFrame.tail() データフレームの最後の5行を表示（デフォルト）
* DataFrame['A'] 列「A」の要素へアクセス
* DataFrame.corr() 各項目の相関係数
* DataFrame.groupby() グルーピングによるデータの集計

```python

#csvデータの読み込み
df = pd.read_csv('/path/to/002-1.csv')
#csvデータの読み込み(ヘッダなし)
df = pd.read_csv('/path/to/002-2.csv', header=None)

#下2行を読まずに取り込み
df2 = pd.read_csv('/path/to/002-3.csv', skipfooter=2, engine="python")
df2.tail()

#カラム名の変更
df2.columns = ["ID", "Evaluation", "Promotion", "Salary", "Quit"]

#カラムの追加
df2['Sex'] = "Male"
#データの相関関係
df2.corr()
#グルーピングによるデータの集計
eva = df2.groupby('Evaluation')
eva.mean()
```

### データフレームの値を処理
* DataFrame.isnull() データフレームのNaNかどうかをBoolean型で返す
* DataFrame.isnull().isum() 値がNaNの要素の合計を確認
* DataFrame.fillna 値がNaNの要素の穴埋め

```py

df3 = pd.read_csv('/path/to/csvfile')
df3.shape
#欠損値の確認
df3.isnull().any()#True or False
df3.isnull().sum()#合計
df3.head(30)

#欠損値を埋める(Heightはソート済み)
df3['Height'] = df3['Height'].fillna(method='ffill')#一つ前のデータの値を欠損データに代入
df3.isnull().sum()
#weightの欠損値は中央値に
df3['Weight'] = df3['Weight'].fillna(df3['Weight'].median())
df3.describe()

#BMIの追加
# lambdaを使って計算，applyメソッドで追加
df3['BMI1'] = df3.apply(lambda row: row['Weight'] / ((row['Height']/100)**2), axis=1)
#関数ged_bmi()を使って計算，applyメソッドで追加
def get_bmi(row):
    return row['Weight'] / ((row['Height']/100)**2)
df3['BMI2'] = df3.apply(get_bmi, axis=1)
df3.head()
#※引数axis=1とすると各行に対して適用される
```

###データセットのマージ
* DataFrame.groupby() グルーピングによるデータの集計
* pd.merge() 2つのデータフレームの結合
* pd.concat() 2つのデータフレームの連結
* DataFrame.reset_index データフレームのindexを振り直す

```py

df4 = pd.read_csv('/path/to/002-4.csv')
df5 = pd.read_csv('/path/to/002-5.csv')
df4.head()
df5.head()

#user_idで集計
user = df5.groupby('user_id')
user.describe()
#データのマージ(user_idをもとに)
df6 = pd.merge(df4, df5, on='user_id')
df6

#データフレームの連結
df6 = pd.DataFrame(data=[['5','3','0'],['6','5','1'],['7','1','6']], columns=['user_id', 'class_id', 'status'])
df7 = pd.concat([df5,df6])
#indexのリセット
df7 = df7.reset_index(drop=True)
df7
```

#Jupyterでの実行結果
https://github.com/hayate242/deep_Learning/blob/master/jupyter/pandas_codexa.ipynb