[Excel的にPandasを使う] pandas  DataFrameのテクニックまとめ

もう、Excel的な集計はPythonでやってしまいたい。慣れるとそのほうが早いし便利ですね。
その時に、いつも調べてしまうような、よく使うテクニックをまとめてみました。

## 1.[基本処理] ファイル読み込み・出力
### CSV読み込み
```python
path='./path/to/csv'
df = pd.read_csv(path)

dataset = pd.read_csv(path,encoding='shift-jis') ## ExcelCSVの場合

dataset = pd.read_csv(path, index_col=2)    # indexを指定して
```

---
### TSV読み込み
```python
dataset = pd.read_table(path)
```

### ファイル出力
```python
df.to_csv(path)
```

---
## 2.[Excel的な基本編集]データ抽出・フィルタ（行・列）＆フィルタ後のデータ更新
Excelでいう基本操作の行や列の追加、フィルタや関数による条件に応じた値代入など
---

### カラム（列）抽出
```python
df[ ['col1','col2','col3'] ] # 列名で抽出
```

### カラム追加・削除
```python
df['new_column'] = 0  # 初期値を0で埋めて追加

df.drop("new_column", axis=1)  # 列(axis=1）を指定して削除
```
---

### 行フィルタ・抽出・削除
```python
df[df['product']=='P1'] # 条件で抽出

df.drop(5) # 行5を削除
df.drop([5,6]) # 行5,6を削除
```

---

### 列の値代入・更新

```python
# =A1*2 的な
s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])

s.apply(lambda x: x * 2)
# a    2
# b    4
# c    6
# dtype: int64

# =IF(A1>0,1,0)的な
Y = df['flg'].apply( lambda x: 1 if x>0 else 0)
```

---

### 一気に更新 ( =A1+5 )

```python
df['point'] += 5
```

### 条件を指定して更新 ( Excel関数の代替 ( =IF(A1>=5,'P1','P2' ) )

```python
df.loc[ df['file_name'].str.contains('ABCD' ) ,'product'] = 'P1'    # 任意の文字列を含む場合

df.loc[ df['point'] >= 5 ,'product'] = 'P1'    #任意の条件に一致する場合
```

---

### 複数の要素を指定して更新 

```python

df.loc['Bob':'Dave', 'age'] = 25    # Bob ~ Daveまで一気に更新
df.loc['Bob':'Dave', 'age'] = [20, 30, 40]    #こんな風にもできる
df.iloc[1:3, 'age'] = 25        # 1 ~ 3まで一気に更新
df.loc[:'Dave', 'age'] = 25     # Daveまで一気に更新
df.loc[:5, 'age'] = 25          # 5まで一気に更新

df.iloc[::2, 0]    # 奇数行

df.iloc[1::2, 0]    # 偶数行
```

---

### 合計・平均,カウント( =sum(A:A) , =average(A:A) )
```python
# mean は数値型のみ集約
df.mean()
# C2    2
# C3    5
# dtype: float64

# sum は 文字列も集約
df.sum()
# C1    ABC
# C2      6
# C3     15
# dtype: object

# sumif , subtotal的に ( =sumif() ,=subtotal(9, A:A) )
df[df['price']>=500].sum()

# count , counif
df.count()
df[df['price']>=500].count()
```
参考：http://sinhrks.hatenablog.com/entry/2014/11/27/232150

---

```python
# 不偏標準偏差
df.std()
# C1    1.290994
# C2    1.290994
# C3    0.577350
# dtype: float64

# 標本標準偏差
df.std(ddof=False)
```
---

### セルの値代入

```python
df.at['Bob', 'age'] = 25    #index名で指定する場合
df.loc['Bob', 'age'] = 25   # locでも可能だが、１つの値更新は、atの方が早い
df.iat[1,0] = 25    # 行番号、列番号で指定（＊いずれも0始まり）
df.iloc[1,0] = 25    # ilocでも可能だが、１つの値更新は、iatの方が早い
```

参考：pandasで任意の位置の値を取得・変更するat, iat, loc, iloc
https://note.nkmk.me/python-pandas-at-iat-loc-iloc/

---

## 3.[Excel VBA的な]ループ処理でなんでも自在に

---

### １行ずつ処理
```python
import pandas as pd
df = pd.DataFrame([[1, 10], [2, 20], [3, 30], [4, 40]], columns=['col1', 'col2'])
 
for index, row in df.iterrows():
    print(row['col1'], row['col2’])
```

---

### 値を更新する

```python
for index, row in df.iterrows():
    row.point += 5
for index, row in df.iterrows():
    df.at[index, 'point'] += 5
```

---

### まとめて取得

```python
for age, point in zip(df['age'], df['point']):
    print(age)
    print(point)
    print('======\n')
```

---

### 1列ずつ処理
```python

import pandas as pd
df = pd.DataFrame([[1, 10], [2, 20], [3, 30], [4, 40]], columns=['col1', 'col2'])
 
for index, col in df.iteritems():
    print(sum(col))
```

---

## 4.PivotTable的な集計

```python
df = pd.DataFrame({'group': ['g1', 'g2', 'g1', 'g2'],
                   'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]}, 
                  columns=['group', 'A', 'B'])
df
#   group  A  B
# 0    g1  1  5
# 1    g2  2  6
# 2    g1  3  7
# 3    g2  4  8

grouped = df.groupby('group')

for name, group in grouped:
    print(name)
    print(group)
    print('')
# g1
#   group  A  B
# 0    g1  1  5
# 2    g1  3  7
# 
# g2
#   group  A  B
# 1    g2  2  6
# 3    g2  4  8
```
---
pivot_table()を使うともっと簡単。

```python
pvTbl = pd.pivot_table(df,values=['A','B'],index='group',aggfunc='sum')
# values : 集計対象のカラムを指定、list or str
# index : 集計キー(list or str)
# aggfunc : mean , sum など集計方法を指定

pvTbl.reset_index(inplace=True)  # 元の状態だと　集計キーをdataFrameのindexとして使用できないため、indexを解除）

```

参考：https://deepage.net/features/pandas-pivot.html#%E3%83%94%E3%83%9C%E3%83%83%E3%83%88%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

---

さっとグループごとの平均を計算

```python
grouped = df.groupby('group')
grouped.apply(np.mean)
#        A  B
# group      
# g1     2  6
# g2     3  7
```

---

## 5.データ連結 (Hlookup, Vlookup的な)

---

### 行（縦）方向に連結

```python
pd.concat([df1, df2 (,・・・)])

df1.append(df2)
df1.append([df2, df4])
```
---

### １行だけ追加も同じように

```python
s1 = pd.Series(['X0', 'X1', 'X2', 'X3'],
               index=['A', 'B', 'C', 'D'], name=10)    # nameはラベル名
df1.append(s1)
```
＊列名が異なる場合は、一方がNaNで埋められる

---

### 横方向の連結

```python
pd.concat([df1, df4], axis=1)

pd.concat([df1, df4], axis=1, join='inner')          # inner join的な（共通indexのみ）
pd.concat([df1, df4], axis=1, join_axes=[df1.index]) # left join的な
```

---

### 横方向の連結(Vlookup的な 厳密にはjoin的な)

```python
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                     'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3']})

right = pd.DataFrame({'key': ['K1', 'K3', 'K5', 'K7'],
                      'C': ['C1', 'C3', 'C5', 'C7'],
                      'D': ['D1', 'D3', 'D5', 'D7']},
                     index=[1, 3, 5, 7])
pd.merge(left, right, on='key', how='left’)    # how: inner / left / right / outer
pd.merge(left, right, on=['key1', 'key2'])    # 複数のキーによる結合も
```

参考：http://sinhrks.hatenablog.com/entry/2015/01/28/073327

その他：pivot_tableで集計してjoinする方法は以下を参照
　https://teratail.com/questions/129198

---

## 6.統計処理 

---

### 基本統計量
```python
df.describe()
```

### パーセンタイル（デシル）

```python
def decile(pddata,targetCol,Sep=10,makeCol='decile'):
    pd['decile'] = pd.qcut(pddata[targetCol], Sep, labels=np.arange(Sep, 0, -1))
    return pd
```

### 相関行列

```python
df.corr()
```