~随時更新~　Python, DataFrameの操作めっちゃまとめ

# はじめに
みなさんはDataFrameの操作を全て覚えているだろうか。自慢ではないが、私は全て覚えることはできておらず、やりたい操作がある度にGoogle検索をかけている。結果、いつも同じWebサイトにとび、「あぁ、そうだこれこれ……」と思い出し、コーディングを進めている。私はこの作業に嫌気がさした。ここに、極めて利己的なまとめページを作成する。もしこれが誰かの助けにもなれば、筆者、望外の喜びである。

## A. データフレームの入出力関連
#### DataFrameの作成
```input_output.py
df = pd.DataFrame([[0,1,2,3], \
                   [4,5,6,7], \
                   [8,9,10,11]], 
                   columns=['col_0','col_1','col_2','col_3'], \
                   index=['row_0','row_1','row_2'])
```
```out.sh
>>> df.head()
       col_0  col_1  col_2  col_3
row_0      0      1      2      3
row_1      4      5      6      7
row_2      8      9     10     11
```
#### indexとcolumnsの取得
```ind_col.py
#　列名、columnsの取得
df.columns
# > Index(['col_0', 'col_1', 'col_2', 'col_3'], dtype='object')

#　インデックスの取得
df.index
# > Index(['row_0', 'row_1', 'row_2'], dtype='object')
```

#### DataFrameの大きさなどを確認
```dfsize.py
df.info()
```

#### Excelファイルの読み込み/書き出し
ここで一点注意。なぜかファイルを読み込み/書き出しの際は、"columns"は"header"、"index"は"index_col"と名前が変わる（何故...?）。
```excel.py
# 読み込み
df = pd.read_excel(filepath, header=0, index_col=0, sheet_name=0)

# 書き出し
# 行名・列名を書き出す必要がないときは、index/headerをFalseにする
df.to_excel(filepath, index=True, header=True)

# ExcelWriterオブジェクトを使うと、複数のpandas.DataFrameオブジェクトを別々のシートに書き出すことが可能。
with pd.ExcelWriter('data/dst/pandas_to_excel_multi.xlsx') as writer:
    df.to_excel(writer, sheet_name='sheet1')
    df2.to_excel(writer, sheet_name='sheet2')
```
対応関係を下表にまとめる。
| |列名の行|行名の列|
|:---|:---|:---|
|DataFrameへのアクセス|columns|index|
|ファイルの読み込み|header|index_col|
|ファイルの書き出し|header|index|

## B. データフレームの値へのアクセス関連
#### 列・行の値を取得してリスト・numpy arrayに変換
```value.py
#　ある列の値を取得し、listに変換
l = df['Column_Name'].tolist()
#　ある行の値を取得し、listに変換
r = df.loc['Index_Name'].tolist()

#ある列の値を取得し、numpy arrayに変換
l = df['Column_Name'].values
#ある行の値を取得し、numpy arrayに変換
r = df.loc['Index_Name'].values
```
この時tolist()をしないと、Series型になる。

## C. 列の値を用いた計算関連
### applyを用いない方法
```calc_non_apply.py
df['B_minus_A'] = df['A'] - df['B']
```

### applyを用いる方法
```calc_apply.py
def divided_by_2(x):
    return float(x) / 2

df['A_divided_by_2'] = df['A'].apply(divided_by_2)
```

## D. ソーティング関連
```sort.py
# ある列に関して、昇順でソート
df.sort_values('Column_Name') 
# 降順にしたい場合は、ascending=Falseとする
df.sort_values('Column_Name', ascending=False) 

#上位100件を抽出
df.sort_values('Column_Name', ascending=False).head(100)
```

## E. query関連
#### 数値操作
```query.py
# 不等式で絞り込み
df.query('Column_Name > 10') #単条件
df.query('Column_Name > 10　and Column_Name_2 < 10') #複数条件

# 変数を使用 (@をつける)
g = 10
df.query('Column_Name > @g')

# リストを使用して、複数項目に一致する行を抽出する
value_list = ['Value1','Value2','Value3']
df.query('Column_Name in @value_list')

# 列名に変数を使用することができる -> f文字を使用
g = 10
cn = 'Column_Name'
df.query(f'{cn} > @g')
# -> Column_Name列に格納されている値が10以上である行を残すことができる！

```
#### 文字列操作
```query.py
#　特定の文字を含む
df.query('Column_Name.str.contains("some")')
#　特定の文字ではじまる
df.query('Column_Name.str.startswith("some")')
#　特定の文字でおわる
df.query('Column_Name.str.endswith("some")')
```
## F. queryを使わない絞り込み
```nonquery.py
# 条件一つ
df[df['Column_Name'] < 0.5]

# 複数条件
df[(df['Column_Name'] < 0.5) and (df['Column_Name_2'] == 'Something')]
df[(df['Column_Name'] < 0.5) or (df['Column_Name_2'] == 'Something')]

# 列名を直接指定して絞り込み
df[['col_1','col_2','col_3']]
# 行名を直接指定して絞り込み
df.loc[['index_1','index_2','index_3']]
```


## G. 空値関連
#### 列Aの空値を列Bの値で埋める
```fillna.py
df['A'].fillna(df['B'], inplace=True)
```

## H. 行・列の追加関連
#### 既存のデータフレームに行を追加
```add_row.py
# 行名を'Ind'とし、新規行を追加
df.loc['Ind'] = ['Str1', 4, 'Str2']
```