目次
Pandasのデータフレーム(DataFrame)
Pandasには2つの主要なデータ構造があります。
Series(シリーズ)が1次元、DataFrame(データフレーム)が2次元です。
2次元というと難しそうに聞こえますが、ようするに、EXCEL表みたいに行と列でデータを保持し、列は「列名」、行数は「行インデックス」として管理します。
このデータの内容を確認したり、統計をとったり、学習データに適しているかどうかを検査したりします。
その結果を踏まえてもろもろの加工を行って、学習データをしあげていくのですけど、列・行の加工は別記事にまとめてます。
なので、今回はデータフレームの結合と分割に絞って整理しようと思います。
なお、コード例は、以下がインポートされている前提とします。
import pandas as pd
例のデータは 以下の要領でCSVファイルを読み込んだ「t」というDataFrameがある想定で例を書いていきます。
t = pd.read_csv('./csvdata/a.csv')
データ結合
2つのDataFrameをくっつけます。
行追加(ユニオン)と列追加(ジョイン)があります。
さらに、ジョインには
- 両方に存在するデータのみ結合する:inner_join
- 片側だけに存在するデータでも結合する:outer_join
があります。
さらに、outer_joinには、構文に書くときの位置関係で
- 左側に存在するデータを軸に結合する:left_outer_join
- 右側に存在するデータを軸に結合する:right_outer_join
があります。
データ結合:行追加(ユニオン)
concatを使います。
t1 = pd.read_csv('csvdata/t_1.csv') t2 = pd.read_csv('csvdata/t_2.csv') t = pd.concat([t1, t2], ignore_index=True)
これでt1にt2の行が追加されます。
ignore_index=Trueを指定しているので、インデックスは0から振りなおされます。
データ結合: 列追加(ジョイン)
以下の2つのデータでJOINしてみます。
こちらが「a.csv」
id name price
0 S01 アイテムA 500
1 S02 アイテムB 850
2 S07 アイテムF 500
3 S08 アイテムG 850
4 S09 アイテムH 1200
こちらが「b.csv」です。
id cate size
0 S01 food big
1 S02 food small
2 S03 drink medium
3 S04 food big
4 S06 drink small
これを、idをキーにして結合します。
データ結合:left outer(左側だけ存在するデータでも結合)
a = pd.read_csv('./csvdata/a.csv') b = pd.read_csv('./csvdata/b.csv') jd = pd.merge(a, b, on="id", how="left") print(jd)
結果です。
id name price cate size
0 S01 アイテムA 500 food big
1 S02 アイテムB 850 food small
2 S07 アイテムF 500 drink medium
3 S08 アイテムG 850 NaN NaN
4 S09 アイテムH 1200 NaN NaN
右側(b.csv)にないカラムは「NaN」になっています。
データ結合:right outer(右側だけ存在するデータでも結合)
a = pd.read_csv('./csvdata/a.csv') b = pd.read_csv('./csvdata/b.csv') jd = pd.merge(a, b, on="id", how="right") print(jd)
結果です。
id name price cate size
0 S01 アイテムA 500.0 food big
1 S02 アイテムB 850.0 food small
2 S07 アイテムF 500.0 drink medium
3 S03 NaN NaN drink medium
4 S04 NaN NaN food big
5 S06 NaN NaN drink small
左側(a.csv)にないカラムは「NaN」になってます。
データ結合:inner(両方に存在するデータのみ結合)
a = pd.read_csv('./csvdata/a.csv') b = pd.read_csv('./csvdata/b.csv') jd = pd.merge(a, b, on="id", how="inner") print(jd)
結果です。
id name price cate size
0 S01 アイテムA 500 food big
1 S02 アイテムB 850 food small
2 S07 アイテムF 500 drink medium
データ結合:列追加
単価と数があるデータに合計額列を追加するパターンです。
例えば、こんなデータを「c」として
id name item_price count
0 S01 アイテムA 500 4
1 S02 アイテムB 850 2
2 S07 アイテムF 500 6
3 S08 アイテムG 850 4
4 S09 アイテムH 1200 1
item_price列とcount列を掛け合わせて、あたらしいprice列を作ると
c["price"] = c["item_price"] * c["count"] print(c.head())
結果はこうなります。
id name item_price count price
0 S01 アイテムA 500 4 2000
1 S02 アイテムB 850 2 1700
2 S07 アイテムF 500 6 3000
3 S08 アイテムG 850 4 3400
4 S09 アイテムH 1200 1 1200
データ分割
行分割する場合と列分割があります。
データ分割:単純に行をわける
例えば、上記のこのDataFrame「c」を、3行とそれ以降にわけます。
c1 = c[:3] c2 = c[3:]
これで、こんな感じにわかれます。
id name item_price count price
0 S01 アイテムA 500 4 2000
1 S02 アイテムB 850 2 1700
2 S07 アイテムF 500 6 3000
id name item_price count price
3 S08 アイテムG 850 4 3400
4 S09 アイテムH 1200 1 1200
Pythonのスライスのイメージです。
データ分割:グルーピングしてグループごとに行分割
ようするに。
id name price cate size
0 S01 アイテムA 500.0 food big
1 S02 アイテムB 850.0 food small
2 S07 アイテムF 500.0 drink medium
3 S03 NaN NaN drink medium
4 S04 NaN NaN food big
5 S06 NaN NaN drink small
こういうデータを「cate」列の「food」グループと「drink」グループ単位で行分割して2つのDataFrameにわけます。
gjd_food = jd.groupby("cate").get_group("food") print(gjd_food) gjd_drink = jd.groupby("cate").get_group("drink") print(gjd_drink)
実行した結果は、こう分かれます。
foodグループと、drinkグループになってます。
id name price cate size
0 S01 アイテムA 500.0 food big
1 S02 アイテムB 850.0 food small
4 S04 NaN NaN food big
id name price cate size
2 S07 アイテムF 500.0 drink medium
3 S03 NaN NaN drink medium
5 S06 NaN NaN drink small
データ分割:列単位の分割
上記の例を、キーとして「id」列を残して、「name」・「price」と「cate」・「size」の2つのDataFrameにわけてみます。
結果はこうなります。
選択した列のみのDataFrameに分割されてます。
id name price
0 S01 アイテムA 500.0
1 S02 アイテムB 850.0
2 S07 アイテムF 500.0
3 S03 NaN NaN
4 S04 NaN NaN
5 S06 NaN NaN
id cate size
0 S01 food big
1 S02 food small
2 S07 drink medium
3 S03 drink medium
4 S04 food big
5 S06 drink small
CSV形式ファイルに保存
結合・分割と関係ないですが、DataFrameをCSVファイルに保存するパターンもついでに書いておきます。
CSV保存をデフォルトでやってしまうと
- セパレータは「,(カンマ)」
- index(行番号)も出力する
- headerも出力する
で保存されます。
でも、普通行番号(index)はいりません。
なので、「false」を指定して保存しないようにします。
あと。
漢字が含まれ、かつ、出力したCSVをWindows版のExcelで使うなら、漢字コードを「SJIS」にします。
1.to_csv("csvdata/r1.csv", index=False, encoding="shift_jis")
ヘダーを出力せず、セパレータを「タブ(\t)」にする場合です。
1.to_csv("csvdata/r1.csv", sep="\t", index=False, header=False)
この回はこんな感じで。
ではでは。