【python】pandas総まとめ（apply / concat）

### はじめに

- バージョン
  - Python: 3.6.8
  - pandas: 1.1.5

　Pandasは、Pythonでデータ分析を行うためのライブラリです。複数のデータに処理を行いたい場合、
for文で書くことが多いと思いますが、pandasで一度DataFrame（表みたいなもの）に変換してから処理を
行うようにすると、シンプルにコードが書けるようになります。

### サンプルデータ

　まずは以下をサンプルデータとします。列col_aとcol_bがあり、行ごとの計算結果を出力します。

```python
import pandas as pd


df = pd.DataFrame(
    data=[[1, 2], [3, 4], [5, 6]],
    columns=["col_a", "col_b"],
)
```

DataFrameとしては以下のようになっています。

||col_a|col_b|
|---|---|---|
|0|1|2|
|1|3|4|
|2|5|6|

### 1列のデータをもとに新たな1列を追加（lambdaを使用）

　列col_aの値を2倍した結果を、新たな列a*2に出力します。**df["col_a"] の部分で列col_aを抽出し、
lambda関数内の変数x（文字は任意）に適用**させます。計算結果は新しい列a*2に出力されます。

```python
df["a*2"] = df["col_a"].apply(lambda x: x * 2)
```

DataFrameとしては以下のようになっています。

||col_a|col_b|a*2|
|---|---|---|---|
|0|1|2|2|
|1|3|4|6|
|2|5|6|10|

### 1列のデータをもとに新たな1列を追加（関数を使用）

　ここでも列col_aの値を2倍した結果を、新たな列a*2に出力します。（出力結果は1つ前と同じなので省略）
1つ前ではlambdaを使用しましたが、ここでは関数value_multipicationを使います。
この関数は、引数として渡された2つの値の積を出力します。

- パターン1
  - 1つ前でlambdaを使った場合と似ていると思います。
- パターン2
  - lambdaを使わない場合の書き方です。このように書くと、関数value_multipicationの  
**第1引数に列col_aの値が自動的に代入**されます。第2引数は関数で使っている変数名と値を  
記載（value_2=2の部分）する必要があるので注意が必要です

```python
def value_multipication(value_1, value_2):
    return value_1 * value_2

df["a*2"] = df["col_a"].apply(lambda x: value_multipication(x, 2))    # パターン1
df["a*2"] = df["col_a"].apply(value_multipication, value_2=2)         # パターン2
```

### 2列のデータをもとに新たな1列を追加

　ここでは列col_aとcol_bの積を、新たな列a*bに出力します。
2列以上のデータを使用する場合は、df.applyのように列名を記載しません。その代わりに、
**lambda関数内で列名を指定**します。また、**axis=1と書くことで、applyを行方向に適用する
ことを宣言**する必要があります。

```python
df["a*b"] = df.apply(lambda x: x["col_a"] * x["col_b"], axis=1)
```

DataFrameとしては以下のようになっています。

||col_a|col_b|a*b|
|---|---|---|---|
|0|1|2|2|
|1|3|4|12|
|2|5|6|30|

### 2列のデータをもとに新たな2列を追加

　ここでは列col_aとcol_bの2倍の値を、それぞれ新たな列a*2とb*2に出力します。
複数列を出力（今回は2列）する場合は、**apply内の計算結果をリストにして、要素数は
出力する列数と同じにします**。さらに、**result_type="expand"**を追加することで、
リストが展開されて新たな列が作成されます。
なお、**axis=1がないとresult_type="expand"が使えない**ので注意が必要です。

```python
df[["a*2", "b*2"]] = df.apply(
    lambda x: [x["col_a"] * 2, x["col_b"] * 2], axis=1, result_type="expand"
)
```

DataFrameとしては以下のようになっています。

||col_a|col_b|a*2|b*2|
|---|---|---|---|---|
|0|1|2|2|4|
|1|3|4|6|8|
|2|5|6|10|12|

### 最終行に列ごとの合計値を追加

　ここでは、最終行に列ごとの合計値を追加します。
concatを使い、もともとのDataFrame（df）と列ごとの合計値のDataFrameを結合させます。

```python
df_new = pd.concat([df,pd.DataFrame(df.sum(), columns=["result"]).T])
```

DataFrameとしては以下のようになっています。

||col_a|col_b|
|---|---|---|
|0|1|2|
|1|3|4|
|2|5|6|
|result|9|12|

列ごとの合計値のDataFrameを作成する部分を詳しく見ていきます。
以下のように列ごとの合計値を出力すると、結合させたいDataFrame（df）に対して行と列が
逆になっていることがわかります。

```python
pd.DataFrame(df.sum(), columns=["result"])
```

||result|
|---|---|
|col_a|9|
|col_b|12|

そこで、DataFrameに対してT（transpose）を追加することによって、行と列を入れ替えることができます。
この状態であれば、もともとのDataFrame（df）と結合することが可能です。

```python
pd.DataFrame(df.sum(), columns=["result"]).T
```

||col_a|col_b|
|---|---|---|
|result|9|12|

### 参考

[pandas.DataFrame.apply — pandas 1.3.4 documentation](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.apply.html)
[pandas.DataFrame.transpose — pandas 1.3.4 documentation](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.transpose.html)

### 関連記事

過去に作成したpandas関連の記事です。
[【python】pandasの活用～1回目：DataFrameの作成、applyの使い方～](https://qiita.com/masa2223/items/ebb84aed1a440f13767e)
[【python】pandasの活用～2回目：axisの使い方～](https://qiita.com/masa2223/items/4303676bcd5004040fd5)
[【python】pandasの活用～3回目：Excelのデータ取り込み～](https://qiita.com/masa2223/items/2f8f5bd585122f0be322)
[【Ansible×pandas】Excelからデータの入力/出力がしたい](https://qiita.com/masa2223/items/bdf5ab7b36565c8b4d62)