| |
Pandas DataFrameのマージ、データ加工、抽出、ファイル出力
マージ
今回のサンプルでは、プログラムの中でDataFrameを定義します。
import pandas as pd
emp = pd.DataFrame({
"ID": ["U123", "U124", "U125", "U126", "U127"],
"名前": ["鈴木", "佐藤", "田中", "渡辺", "山本"],
"組織ID": ["D1", "D2", "D3", "D2", "D1"]
})
org = pd.DataFrame({
"組織ID": ["D1", "D2", "D3"],
"組織名": ["営業部", "製造部", "経理部"]
})
|
上で定義した2つのDataFrameをいきなりおもむろにマージして1個にしてみましょう。はい。
df = pd.merge(emp, org)
print(df.head(10))
|
ちゃんと1個になっていることが確認できると思います。
このように、2つのDataFrameに、列名が共通する列が1つだけある場合は、
単にmerge関数でDataFrameを2つ指定するだけで全てが行われます。
そうでない場合の方法は後述することにして、先にこのデータを使って色々やってみます。
# 列の一覧を表示
print(df.columns)
# Index(['ID', '名前', '組織ID', '組織名'], dtype='object')
# 単純に連結したDataFrameの列の並びに沿っていることが分かります。
# 列名から列番号(先頭が0)を取得
print(df.columns.get_loc("組織名"))
# locで指定した人の組織名を表示
print(df.loc[2,"組織名"])
# ilocで指定した人の組織名を表示
print(df.iloc[2, 3])
# 値を変更する
df.iloc[2, 3] = "第二製造部"
print(df)
# 年齢というSeriesを定義して、DataFrameに追加する
ages = pd.Series([30,27,35,38,29])
df["年齢"] = ages
print(df)
|
ファイル出力
# CSV出力
df.to_csv("/content/drive/MyDrive/colaroot/data/output_merged.csv")
# Excel出力
df.to_excel("/content/drive/MyDrive/colaroot/data/output_merged.xlsx")
|
条件によるデータの抽出
# 条件を満たす行だけを抽出
print(df[df["年齢"] >= 30])
# ID 名前 組織ID 組織名 年齢
#0 U123 鈴木 D1 営業部 30
#2 U124 佐藤 D2 第二製造部 35
#3 U126 渡辺 D2 製造部 38
# 複数の条件を連結するときは、&&や||ではなく&と|なので注意。
# また丸括弧は省略できないらしいので注意
print(df[(df["年齢"] >= 30) | (df["組織ID"] == "D1")])
# ID 名前 組織ID 組織名 年齢
#0 U123 鈴木 D1 営業部 30
#1 U127 山本 D1 営業部 27
#2 U124 佐藤 D2 第二製造部 35
#3 U126 渡辺 D2 製造部 38
# 上の例ではdf[]を二重に記述する必要がありますが、queryを使うとSQLのWHERE句みたいに書けます。
# ちなみに列名が空白文字を含む場合は、バッククォートで囲めばOKだそう
print(df.query("年齢 >= 30"))
# queryの場合はandやorになる。ORのように大文字にはできないので注意
print(df.query("年齢 >= 30 or 組織ID == 'D1'"))
# 「30歳か35歳」という条件はisinで抽出できる
print(df[df["年齢"].isin([30,35])])
# ID 名前 組織ID 組織名 年齢
#0 U123 鈴木 D1 営業部 30
#2 U124 佐藤 D2 第二製造部 35
# 同じ操作のquery版。こちらは角括弧ではなく丸括弧です。覚えるしかない
print(df.query("年齢 in (30,35)"))
# 変数が使える。変数はqueryの中で@をつけて参照できる
x = 35
print(df.query("年齢 >= @x"))
x = (35,36,37)
print(df.query("年齢 in @x"))
|
ソートやその他の操作
# 最大値の取得
print(df["年齢"].max())
# 年齢の降順でソート。並び順が変わるだけで、Indexはソートされないので注意
a = df.sort_values(by="年齢")
print(a)
# ID 名前 組織ID 組織名 年齢
#1 U127 山本 D1 営業部 27
#4 U125 田中 D3 経理部 29
#0 U123 鈴木 D1 営業部 30
#2 U124 佐藤 D2 第二製造部 35
#3 U126 渡辺 D2 製造部 38
# 組織IDの昇順、年齢の降順でソート
a = df.sort_values(by=["組織ID","年齢"], ascending=[True,False])
print(a)
|
マージ処理のオプション
emp2 = pd.DataFrame({
"ID": ["U123", "U124", "U125", "U126", "U127"],
"名前": ["鈴木", "佐藤", "田中", "渡辺", "山本"],
"所属": ["D1", "D2", "D3", "D2", "D4"]
})
org2 = pd.DataFrame({
"組織ID": ["D1", "D2", "D3"],
"組織名": ["営業部", "製造部", "経理部"]
})
df2 = pd.merge(emp2, org2, left_on="所属", right_on="組織ID", how="left")
print(df2)
# ID 名前 所属 組織ID 組織名
#0 U123 鈴木 D1 D1 営業部
#1 U124 佐藤 D2 D2 製造部
#2 U125 田中 D3 D3 経理部
#3 U126 渡辺 D2 D2 製造部
#4 U127 山本 D4 NaN NaN
|
冒頭で行ったマージ処理の補足です。この例では二つの事を説明しています。
まず、DataFrameの連結(JOIN)に使いたい列の名前が異なる場合はどうするの?
上の例のように、merge関数のleft_onで左のDataFrameの列名(ここでは"所属")、
right_onで右の列名(ここでは"組織名")を指定すればOKです。
またその所属列のように、連結キー列の値の中に片側にしかないものがある場合(この例では"D4")どうなるの?
これは、SQLの用語でいわゆる外部結合の指定と同じことがmerge関数のhow=で可能です。
上記の例ではleft、つまり「左外部結合」、つまり左側のDataFrameの連結キーに右側にはない物がある場合、
そのレコードを削除することはせずに足りない情報の部分をNaN(SQLのNULLに相当)で補っています。
howに指定できる値は4種類、inner、left、right、outerです。SQLの外部結合をご存じの方は多分類推通りの処理になります。
howを省略した際のデフォルトはinner、つまりINNER JOIN=内部結合、
つまり連結キー列の値が片方にしかない場合、その行は削除されて連結されます。

(first uploaded 2024/01/06 last updated (not ever), URANO398)
|