pythonのpandasで2つのファイルを比較、結合(merge)等の処理を行うやり方のサンプル

pythonのpandasで2つのファイルを比較、結合(merge)等の処理を行うやり方のサンプル
pythonのpandasで2つのファイルを
比較、結合等の操作を行うやり方を忘れないうちにメモ。
エクセルで作ったファイル(csv形式)を読む為に文字コードの指定、
mergeを使って2つのファイルを外部結合、
内部データの比較方法、列の新規追加、
結合したデータをファイルに出力する方法を
簡単なユースケースを元に説明します。

公式サイトがhttps://pandas.pydata.org/pandas-docs/stable/にあるので、
さらに細かいものはそちらを参照ください。

ユースケース

担当者ごとの1日の売り上げデータをファイルに出力して、
それを比較し、ノルマがクリアできているか確認する。
データは下記の通り2/1と2/2の2つのcsvファイルを用意。
上が2/1のデータ(sales_0201.csv)。下が2/2のデータ(sales_0202.csv)
グループIDID売上お休み
Ayamada1000
Byamada500
Asatou200
Aikeda300
グループIDID売上お休み
Ayamada100
Byamada200
Asatou0TRUE
Aikeda600
B新人

サンプルソース

import pandas as pd

before_pd = pd.read_csv('sales_0201.csv', encoding='shift_jis')
after_pd = pd.read_csv('sales_0202.csv', encoding='shift_jis')

f=pd.merge(before_pd, after_pd, 
           on=['グループID', 'ID'], suffixes=['_0201', '_0202'], how='outer')

f['is_ノルマクリア'] =  (
    (f['売上_0201'] < f['売上_0202'])
    | ((f['売上_0202'] == 0) & (f['お休み_0202'] == True))
    | f['売上_0202'].isnull()
)
f['売上合計'] = (f[['売上_0201','売上_0202']].sum(axis='columns'))

f.to_csv('result.csv',index=False, encoding='shift_jis')

サンプル実行結果(result.csv)

グループIDID売上_0201お休み_0201売上_0202お休み_0202is_ノルマクリア売上合計
Ayamada1000100FALSE1100
Byamada500200FALSE700
Asatou2000TRUETRUE200
Aikeda300600TRUE900
B新人TRUE0
列追加仕様としては、
ノルマクリアの確認として、前日より売り上げがあることを確認します。
ただし、お休みで売上0の人。新規登録されて売上データが無い人(新人)
は無条件ノルマクリアにします(列:is_ノルマクリア)。
売上合計は売り上げの合計値を設定します(列:売上合計)。

操作の説明

ファイルをエンコードする方法

before_pd = pd.read_csv('sales_0201.csv', encoding="shift_jis")
after_pd = pd.read_csv('sales_0202.csv', encoding="shift_jis")

のread_csvでファイルを読み込み、その属性に encoding を指定可能です。
エクセルは文字コードshift_jisなので、それを指定します。

2つのファイルを外部結合

f=pd.merge(before_pd, after_pd, on=['グループID', 'ID'], suffixes=['_0201', '_0202'], how='outer')

merge を利用して結合します。
DBの外部結合とほぼ同じ感覚で利用可能。
on=でキーとなる列名を設定します。複数の場合はリストを利用します。
 ⇒IDがyamadaでかぶっているので、グループIDも指定する必要有。
suffixes=は列に追加される末尾文字です。
howはどのように結合するか結合方法を指定します。
パターンは下記の通り。
内部結合(inner_join): how='inner'
左結合(left_join): how='left'
右結合(right_join): how='right'
外部結合(outer_join): how='outer'

結合したデータを判定し、列を追加

f['is_ノルマクリア'] =  (
    (f['売上_0201'] < f['売上_0202'])
    | ((f['売上_0202'] == 0) | (f['お休み_0202'] == True))
    | f['売上_0202'].isnull()
)
f[列名]で列を指定し、比較式を記述することが可能。
比較は行単位で行われます。
上記では
(数値の比較 or (数値比較 and 文字列の比較) or データ無し)
の条件結果を列に追加しています。
and は& or は|で指定。()でくくると判定を絞れるのは
pythonの記述とかそのままです。
isnull()でデータが存在しないデータかどうかを判定します。
 ⇒f['売上_0202'] == Noneとかはできないので注意。
f['is_ノルマクリア'] =の箇所で追加したい列名を記述します。

行単位の合計値の計算

f['売上合計'] = (f[['売上_0201','売上_0202']].sum(axis='columns'))
売上の列でそれぞれsuffixesで指定した文字列を加えて、
ファイル1、ファイル2にある値の合計値をsumで算出します。
f[['売上_0201','売上_0202']]の箇所で列の指定、
axis='columns' の箇所で行の計算が可能。ちなみに index と指定すると列の計算になります。

ファイル出力

f.to_csv('result.csv',index=False, encoding='shift_jis')
to_csvでcsvファイル出力します。
pandasではファイル出力すると、行のindexを示す列を先頭に追加しますが、
index=False を指定することによりそれを除外します。
人が確認するデータの想定なので、今回は除外。
encoding は文字コードを指定し出力します。

ITカテゴリの最新記事